+ */
+class HelpCommand extends Command
+{
+ /**
+ * @var \Symfony\Component\Console\Command\Command
+ */
+ private $command;
+ /**
+ * @return void
+ */
+ protected function configure()
+ {
+ $this->ignoreValidationErrors();
+ $this->setName('help')->setDefinition([new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help', function () {
+ return \array_keys((new ApplicationDescription($this->getApplication()))->getCommands());
+ }), new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt', function () {
+ return (new DescriptorHelper())->getFormats();
+ }), new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help')])->setDescription('Display help for a command')->setHelp(<<<'EOF'
+The %command.name% command displays help for a given command:
+
+ %command.full_name% list
+
+You can also output the help in other formats by using the --format option:
+
+ %command.full_name% --format=xml list
+
+To display the list of available commands, please use the list command.
+EOF
+);
+ }
+ /**
+ * @return void
+ */
+ public function setCommand(Command $command)
+ {
+ $this->command = $command;
+ }
+ protected function execute(InputInterface $input, OutputInterface $output) : int
+ {
+ $this->command = $this->command ?? $this->getApplication()->find($input->getArgument('command_name'));
+ $helper = new DescriptorHelper();
+ $helper->describe($output, $this->command, ['format' => $input->getOption('format'), 'raw_text' => $input->getOption('raw')]);
+ unset($this->command);
+ return 0;
+ }
+}
diff --git a/vendor/symfony/console/Command/LazyCommand.php b/vendor/symfony/console/Command/LazyCommand.php
new file mode 100644
index 00000000..42281408
--- /dev/null
+++ b/vendor/symfony/console/Command/LazyCommand.php
@@ -0,0 +1,188 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Command;
+
+use ClassLeak202307\Symfony\Component\Console\Application;
+use ClassLeak202307\Symfony\Component\Console\Completion\CompletionInput;
+use ClassLeak202307\Symfony\Component\Console\Completion\CompletionSuggestions;
+use ClassLeak202307\Symfony\Component\Console\Completion\Suggestion;
+use ClassLeak202307\Symfony\Component\Console\Helper\HelperInterface;
+use ClassLeak202307\Symfony\Component\Console\Helper\HelperSet;
+use ClassLeak202307\Symfony\Component\Console\Input\InputDefinition;
+use ClassLeak202307\Symfony\Component\Console\Input\InputInterface;
+use ClassLeak202307\Symfony\Component\Console\Output\OutputInterface;
+/**
+ * @author Nicolas Grekas
+ */
+final class LazyCommand extends Command
+{
+ /**
+ * @var \Closure|\Symfony\Component\Console\Command\Command
+ */
+ private $command;
+ /**
+ * @var bool|null
+ */
+ private $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 (1 > \func_num_args()) {
+ trigger_deprecation('symfony/console', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
+ }
+ 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);
+ }
+ /**
+ * @return $this
+ */
+ public function setCode(callable $code)
+ {
+ $this->getCommand()->setCode($code);
+ return $this;
+ }
+ /**
+ * @internal
+ */
+ public function mergeApplicationDefinition(bool $mergeArgs = \true) : void
+ {
+ $this->getCommand()->mergeApplicationDefinition($mergeArgs);
+ }
+ /**
+ * @param mixed[]|\Symfony\Component\Console\Input\InputDefinition $definition
+ * @return $this
+ */
+ public function setDefinition($definition)
+ {
+ $this->getCommand()->setDefinition($definition);
+ return $this;
+ }
+ public function getDefinition() : InputDefinition
+ {
+ return $this->getCommand()->getDefinition();
+ }
+ public function getNativeDefinition() : InputDefinition
+ {
+ return $this->getCommand()->getNativeDefinition();
+ }
+ /**
+ * @param array|\Closure(CompletionInput,CompletionSuggestions):list $suggestedValues The values used for input completion
+ * @param mixed $default
+ * @return $this
+ */
+ public function addArgument(string $name, int $mode = null, string $description = '', $default = null)
+ {
+ $suggestedValues = 5 <= \func_num_args() ? \func_get_arg(4) : [];
+ $this->getCommand()->addArgument($name, $mode, $description, $default, $suggestedValues);
+ return $this;
+ }
+ /**
+ * @param array|\Closure(CompletionInput,CompletionSuggestions):list $suggestedValues The values used for input completion
+ * @param string|mixed[] $shortcut
+ * @param mixed $default
+ * @return $this
+ */
+ public function addOption(string $name, $shortcut = null, int $mode = null, string $description = '', $default = null)
+ {
+ $suggestedValues = 6 <= \func_num_args() ? \func_get_arg(5) : [];
+ $this->getCommand()->addOption($name, $shortcut, $mode, $description, $default, $suggestedValues);
+ return $this;
+ }
+ /**
+ * @return $this
+ */
+ public function setProcessTitle(string $title)
+ {
+ $this->getCommand()->setProcessTitle($title);
+ return $this;
+ }
+ /**
+ * @return $this
+ */
+ public function setHelp(string $help)
+ {
+ $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);
+ }
+ /**
+ * @return $this
+ */
+ public function addUsage(string $usage)
+ {
+ $this->getCommand()->addUsage($usage);
+ return $this;
+ }
+ public function getUsages() : array
+ {
+ return $this->getCommand()->getUsages();
+ }
+ public function getHelper(string $name) : HelperInterface
+ {
+ 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;
+ }
+}
diff --git a/vendor/symfony/console/Command/ListCommand.php b/vendor/symfony/console/Command/ListCommand.php
new file mode 100644
index 00000000..83513717
--- /dev/null
+++ b/vendor/symfony/console/Command/ListCommand.php
@@ -0,0 +1,60 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Command;
+
+use ClassLeak202307\Symfony\Component\Console\Descriptor\ApplicationDescription;
+use ClassLeak202307\Symfony\Component\Console\Helper\DescriptorHelper;
+use ClassLeak202307\Symfony\Component\Console\Input\InputArgument;
+use ClassLeak202307\Symfony\Component\Console\Input\InputInterface;
+use ClassLeak202307\Symfony\Component\Console\Input\InputOption;
+use ClassLeak202307\Symfony\Component\Console\Output\OutputInterface;
+/**
+ * ListCommand displays the list of all available commands for the application.
+ *
+ * @author Fabien Potencier
+ */
+class ListCommand extends Command
+{
+ /**
+ * @return void
+ */
+ protected function configure()
+ {
+ $this->setName('list')->setDefinition([new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name', null, function () {
+ return \array_keys((new ApplicationDescription($this->getApplication()))->getNamespaces());
+ }), 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', function () {
+ return (new DescriptorHelper())->getFormats();
+ }), new InputOption('short', null, InputOption::VALUE_NONE, 'To skip describing commands\' arguments')])->setDescription('List commands')->setHelp(<<<'EOF'
+The %command.name% command lists all commands:
+
+ %command.full_name%
+
+You can also display the commands for a specific namespace:
+
+ %command.full_name% test
+
+You can also output the information in other formats by using the --format option:
+
+ %command.full_name% --format=xml
+
+It's also possible to get raw list of commands (useful for embedding command runner):
+
+ %command.full_name% --raw
+EOF
+);
+ }
+ protected function execute(InputInterface $input, OutputInterface $output) : int
+ {
+ $helper = new DescriptorHelper();
+ $helper->describe($output, $this->getApplication(), ['format' => $input->getOption('format'), 'raw_text' => $input->getOption('raw'), 'namespace' => $input->getArgument('namespace'), 'short' => $input->getOption('short')]);
+ return 0;
+ }
+}
diff --git a/vendor/symfony/console/Command/LockableTrait.php b/vendor/symfony/console/Command/LockableTrait.php
new file mode 100644
index 00000000..e590241b
--- /dev/null
+++ b/vendor/symfony/console/Command/LockableTrait.php
@@ -0,0 +1,62 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Command;
+
+use ClassLeak202307\Symfony\Component\Console\Exception\LogicException;
+use ClassLeak202307\Symfony\Component\Lock\LockFactory;
+use ClassLeak202307\Symfony\Component\Lock\LockInterface;
+use ClassLeak202307\Symfony\Component\Lock\Store\FlockStore;
+use ClassLeak202307\Symfony\Component\Lock\Store\SemaphoreStore;
+/**
+ * Basic lock feature for commands.
+ *
+ * @author Geoffrey Brier
+ */
+trait LockableTrait
+{
+ /**
+ * @var \Symfony\Component\Lock\LockInterface|null
+ */
+ private $lock;
+ /**
+ * Locks a command.
+ */
+ private function lock(string $name = null, bool $blocking = \false) : bool
+ {
+ if (!\class_exists(SemaphoreStore::class)) {
+ throw new LogicException('To enable the locking feature you must install the symfony/lock component. Try running "composer require symfony/lock".');
+ }
+ if (null !== $this->lock) {
+ throw new LogicException('A lock is already in place.');
+ }
+ if (SemaphoreStore::isSupported()) {
+ $store = new SemaphoreStore();
+ } else {
+ $store = new FlockStore();
+ }
+ $this->lock = (new LockFactory($store))->createLock($name ?: $this->getName());
+ if (!$this->lock->acquire($blocking)) {
+ $this->lock = null;
+ return \false;
+ }
+ return \true;
+ }
+ /**
+ * Releases the command lock if there is one.
+ */
+ private function release() : void
+ {
+ if ($this->lock) {
+ $this->lock->release();
+ $this->lock = null;
+ }
+ }
+}
diff --git a/vendor/symfony/console/Command/SignalableCommandInterface.php b/vendor/symfony/console/Command/SignalableCommandInterface.php
new file mode 100644
index 00000000..fa894eaf
--- /dev/null
+++ b/vendor/symfony/console/Command/SignalableCommandInterface.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Command;
+
+/**
+ * Interface for command reacting to signal.
+ *
+ * @author Grégoire Pineau
+ */
+interface SignalableCommandInterface
+{
+ /**
+ * Returns the list of signals to subscribe.
+ */
+ public function getSubscribedSignals() : array;
+ /**
+ * The method will be called when the application is signaled.
+ *
+ * @param int|false $previousExitCode
+ * @return int|false The exit code to return or false to continue the normal execution
+ */
+ public function handleSignal(int $signal);
+}
diff --git a/vendor/symfony/console/CommandLoader/CommandLoaderInterface.php b/vendor/symfony/console/CommandLoader/CommandLoaderInterface.php
new file mode 100644
index 00000000..e1225af0
--- /dev/null
+++ b/vendor/symfony/console/CommandLoader/CommandLoaderInterface.php
@@ -0,0 +1,34 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\CommandLoader;
+
+use ClassLeak202307\Symfony\Component\Console\Command\Command;
+use ClassLeak202307\Symfony\Component\Console\Exception\CommandNotFoundException;
+/**
+ * @author Robin Chalas
+ */
+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;
+}
diff --git a/vendor/symfony/console/CommandLoader/ContainerCommandLoader.php b/vendor/symfony/console/CommandLoader/ContainerCommandLoader.php
new file mode 100644
index 00000000..a089d5e1
--- /dev/null
+++ b/vendor/symfony/console/CommandLoader/ContainerCommandLoader.php
@@ -0,0 +1,54 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\CommandLoader;
+
+use ClassLeak202307\Psr\Container\ContainerInterface;
+use ClassLeak202307\Symfony\Component\Console\Command\Command;
+use ClassLeak202307\Symfony\Component\Console\Exception\CommandNotFoundException;
+/**
+ * Loads commands from a PSR-11 container.
+ *
+ * @author Robin Chalas
+ */
+class ContainerCommandLoader implements CommandLoaderInterface
+{
+ /**
+ * @var \Psr\Container\ContainerInterface
+ */
+ private $container;
+ /**
+ * @var mixed[]
+ */
+ private $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;
+ }
+ 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]);
+ }
+ public function has(string $name) : bool
+ {
+ return isset($this->commandMap[$name]) && $this->container->has($this->commandMap[$name]);
+ }
+ public function getNames() : array
+ {
+ return \array_keys($this->commandMap);
+ }
+}
diff --git a/vendor/symfony/console/CommandLoader/FactoryCommandLoader.php b/vendor/symfony/console/CommandLoader/FactoryCommandLoader.php
new file mode 100644
index 00000000..a08c6572
--- /dev/null
+++ b/vendor/symfony/console/CommandLoader/FactoryCommandLoader.php
@@ -0,0 +1,49 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\CommandLoader;
+
+use ClassLeak202307\Symfony\Component\Console\Command\Command;
+use ClassLeak202307\Symfony\Component\Console\Exception\CommandNotFoundException;
+/**
+ * A simple command loader using factories to instantiate commands lazily.
+ *
+ * @author Maxime Steinhausser
+ */
+class FactoryCommandLoader implements CommandLoaderInterface
+{
+ /**
+ * @var mixed[]
+ */
+ private $factories;
+ /**
+ * @param callable[] $factories Indexed by command names
+ */
+ public function __construct(array $factories)
+ {
+ $this->factories = $factories;
+ }
+ public function has(string $name) : bool
+ {
+ return isset($this->factories[$name]);
+ }
+ 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();
+ }
+ public function getNames() : array
+ {
+ return \array_keys($this->factories);
+ }
+}
diff --git a/vendor/symfony/console/Completion/CompletionInput.php b/vendor/symfony/console/Completion/CompletionInput.php
new file mode 100644
index 00000000..f7147966
--- /dev/null
+++ b/vendor/symfony/console/Completion/CompletionInput.php
@@ -0,0 +1,210 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Completion;
+
+use ClassLeak202307\Symfony\Component\Console\Exception\RuntimeException;
+use ClassLeak202307\Symfony\Component\Console\Input\ArgvInput;
+use ClassLeak202307\Symfony\Component\Console\Input\InputDefinition;
+use ClassLeak202307\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
+ */
+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;
+ 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)([\'"]?)(.+?)(?tokens = $tokens;
+ $input->currentIndex = $currentIndex;
+ return $input;
+ }
+ 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 (($option2 = $option) ? $option2->acceptValue() : null) {
+ $this->completionType = self::TYPE_OPTION_VALUE;
+ $this->completionName = $option->getName();
+ $this->completionValue = $optionValue ?: (\strncmp($optionToken, '--', \strlen('--')) !== 0 ? \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 (($previousOption2 = $previousOption) ? $previousOption2->acceptValue() : null) {
+ $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)) {
+ \end($argumentValue);
+ $this->completionValue = $argumentValue ? $argumentValue[\key($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 $exception) {
+ // 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() : string
+ {
+ $str = '';
+ foreach ($this->tokens as $i => $token) {
+ $str .= $token;
+ if ($this->currentIndex === $i) {
+ $str .= '|';
+ }
+ $str .= ' ';
+ }
+ if ($this->currentIndex > $i) {
+ $str .= '|';
+ }
+ return \rtrim($str);
+ }
+}
diff --git a/vendor/symfony/console/Completion/CompletionSuggestions.php b/vendor/symfony/console/Completion/CompletionSuggestions.php
new file mode 100644
index 00000000..4e6ac6bb
--- /dev/null
+++ b/vendor/symfony/console/Completion/CompletionSuggestions.php
@@ -0,0 +1,86 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Completion;
+
+use ClassLeak202307\Symfony\Component\Console\Input\InputOption;
+/**
+ * Stores all completion suggestions for the current input.
+ *
+ * @author Wouter de Jong
+ */
+final class CompletionSuggestions
+{
+ private $valueSuggestions = [];
+ private $optionSuggestions = [];
+ /**
+ * Add a suggested value for an input option or argument.
+ *
+ * @return $this
+ * @param string|\Symfony\Component\Console\Completion\Suggestion $value
+ */
+ public function suggestValue($value)
+ {
+ $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 $values
+ *
+ * @return $this
+ */
+ public function suggestValues(array $values)
+ {
+ foreach ($values as $value) {
+ $this->suggestValue($value);
+ }
+ return $this;
+ }
+ /**
+ * Add a suggestion for an input option name.
+ *
+ * @return $this
+ */
+ public function suggestOption(InputOption $option)
+ {
+ $this->optionSuggestions[] = $option;
+ return $this;
+ }
+ /**
+ * Add multiple suggestions for input option names at once.
+ *
+ * @param InputOption[] $options
+ *
+ * @return $this
+ */
+ public function suggestOptions(array $options)
+ {
+ 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;
+ }
+}
diff --git a/vendor/symfony/console/Completion/Output/BashCompletionOutput.php b/vendor/symfony/console/Completion/Output/BashCompletionOutput.php
new file mode 100644
index 00000000..7a798942
--- /dev/null
+++ b/vendor/symfony/console/Completion/Output/BashCompletionOutput.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Completion\Output;
+
+use ClassLeak202307\Symfony\Component\Console\Completion\CompletionSuggestions;
+use ClassLeak202307\Symfony\Component\Console\Output\OutputInterface;
+/**
+ * @author Wouter de Jong
+ */
+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));
+ }
+}
diff --git a/vendor/symfony/console/Completion/Output/CompletionOutputInterface.php b/vendor/symfony/console/Completion/Output/CompletionOutputInterface.php
new file mode 100644
index 00000000..d978d84a
--- /dev/null
+++ b/vendor/symfony/console/Completion/Output/CompletionOutputInterface.php
@@ -0,0 +1,23 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Completion\Output;
+
+use ClassLeak202307\Symfony\Component\Console\Completion\CompletionSuggestions;
+use ClassLeak202307\Symfony\Component\Console\Output\OutputInterface;
+/**
+ * Transforms the {@see CompletionSuggestions} object into output readable by the shell completion.
+ *
+ * @author Wouter de Jong
+ */
+interface CompletionOutputInterface
+{
+ public function write(CompletionSuggestions $suggestions, OutputInterface $output) : void;
+}
diff --git a/vendor/symfony/console/Completion/Output/FishCompletionOutput.php b/vendor/symfony/console/Completion/Output/FishCompletionOutput.php
new file mode 100644
index 00000000..697b07b4
--- /dev/null
+++ b/vendor/symfony/console/Completion/Output/FishCompletionOutput.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Completion\Output;
+
+use ClassLeak202307\Symfony\Component\Console\Completion\CompletionSuggestions;
+use ClassLeak202307\Symfony\Component\Console\Output\OutputInterface;
+/**
+ * @author Guillaume Aveline
+ */
+class FishCompletionOutput 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->write(\implode("\n", $values));
+ }
+}
diff --git a/vendor/symfony/console/Completion/Output/ZshCompletionOutput.php b/vendor/symfony/console/Completion/Output/ZshCompletionOutput.php
new file mode 100644
index 00000000..7900fce6
--- /dev/null
+++ b/vendor/symfony/console/Completion/Output/ZshCompletionOutput.php
@@ -0,0 +1,34 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Completion\Output;
+
+use ClassLeak202307\Symfony\Component\Console\Completion\CompletionSuggestions;
+use ClassLeak202307\Symfony\Component\Console\Output\OutputInterface;
+/**
+ * @author Jitendra A
+ */
+class ZshCompletionOutput implements CompletionOutputInterface
+{
+ public function write(CompletionSuggestions $suggestions, OutputInterface $output) : void
+ {
+ $values = [];
+ foreach ($suggestions->getValueSuggestions() as $value) {
+ $values[] = $value->getValue() . ($value->getDescription() ? "\t" . $value->getDescription() : '');
+ }
+ foreach ($suggestions->getOptionSuggestions() as $option) {
+ $values[] = '--' . $option->getName() . ($option->getDescription() ? "\t" . $option->getDescription() : '');
+ if ($option->isNegatable()) {
+ $values[] = '--no-' . $option->getName() . ($option->getDescription() ? "\t" . $option->getDescription() : '');
+ }
+ }
+ $output->write(\implode("\n", $values) . "\n");
+ }
+}
diff --git a/vendor/symfony/console/Completion/Suggestion.php b/vendor/symfony/console/Completion/Suggestion.php
new file mode 100644
index 00000000..71ef8ba2
--- /dev/null
+++ b/vendor/symfony/console/Completion/Suggestion.php
@@ -0,0 +1,47 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Completion;
+
+/**
+ * Represents a single suggested value.
+ *
+ * @author Wouter de Jong
+ */
+class Suggestion
+{
+ /**
+ * @readonly
+ * @var string
+ */
+ private $value;
+ /**
+ * @readonly
+ * @var string
+ */
+ private $description = '';
+ public function __construct(string $value, string $description = '')
+ {
+ $this->value = $value;
+ $this->description = $description;
+ }
+ public function getValue() : string
+ {
+ return $this->value;
+ }
+ public function getDescription() : string
+ {
+ return $this->description;
+ }
+ public function __toString() : string
+ {
+ return $this->getValue();
+ }
+}
diff --git a/vendor/symfony/console/ConsoleEvents.php b/vendor/symfony/console/ConsoleEvents.php
new file mode 100644
index 00000000..3de3a702
--- /dev/null
+++ b/vendor/symfony/console/ConsoleEvents.php
@@ -0,0 +1,61 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console;
+
+use ClassLeak202307\Symfony\Component\Console\Event\ConsoleCommandEvent;
+use ClassLeak202307\Symfony\Component\Console\Event\ConsoleErrorEvent;
+use ClassLeak202307\Symfony\Component\Console\Event\ConsoleSignalEvent;
+use ClassLeak202307\Symfony\Component\Console\Event\ConsoleTerminateEvent;
+/**
+ * Contains all events dispatched by an Application.
+ *
+ * @author Francesco Levorato
+ */
+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 handed to the command.
+ *
+ * @Event("Symfony\Component\Console\Event\ConsoleCommandEvent")
+ */
+ 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")
+ */
+ public const TERMINATE = 'console.terminate';
+ /**
+ * The ERROR event occurs when an uncaught exception or error appears.
+ *
+ * This event allows you to deal with the exception/error or
+ * to modify the thrown exception.
+ *
+ * @Event("Symfony\Component\Console\Event\ConsoleErrorEvent")
+ */
+ 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];
+}
diff --git a/vendor/symfony/console/Cursor.php b/vendor/symfony/console/Cursor.php
new file mode 100644
index 00000000..3d396051
--- /dev/null
+++ b/vendor/symfony/console/Cursor.php
@@ -0,0 +1,167 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console;
+
+use ClassLeak202307\Symfony\Component\Console\Output\OutputInterface;
+/**
+ * @author Pierre du Plessis
+ */
+final class Cursor
+{
+ /**
+ * @var \Symfony\Component\Console\Output\OutputInterface
+ */
+ 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)
+ {
+ $this->output->write(\sprintf("\x1b[%dA", $lines));
+ return $this;
+ }
+ /**
+ * @return $this
+ */
+ public function moveDown(int $lines = 1)
+ {
+ $this->output->write(\sprintf("\x1b[%dB", $lines));
+ return $this;
+ }
+ /**
+ * @return $this
+ */
+ public function moveRight(int $columns = 1)
+ {
+ $this->output->write(\sprintf("\x1b[%dC", $columns));
+ return $this;
+ }
+ /**
+ * @return $this
+ */
+ public function moveLeft(int $columns = 1)
+ {
+ $this->output->write(\sprintf("\x1b[%dD", $columns));
+ return $this;
+ }
+ /**
+ * @return $this
+ */
+ public function moveToColumn(int $column)
+ {
+ $this->output->write(\sprintf("\x1b[%dG", $column));
+ return $this;
+ }
+ /**
+ * @return $this
+ */
+ public function moveToPosition(int $column, int $row)
+ {
+ $this->output->write(\sprintf("\x1b[%d;%dH", $row + 1, $column));
+ return $this;
+ }
+ /**
+ * @return $this
+ */
+ public function savePosition()
+ {
+ $this->output->write("\x1b7");
+ return $this;
+ }
+ /**
+ * @return $this
+ */
+ public function restorePosition()
+ {
+ $this->output->write("\x1b8");
+ return $this;
+ }
+ /**
+ * @return $this
+ */
+ public function hide()
+ {
+ $this->output->write("\x1b[?25l");
+ return $this;
+ }
+ /**
+ * @return $this
+ */
+ public function show()
+ {
+ $this->output->write("\x1b[?25h\x1b[?0c");
+ return $this;
+ }
+ /**
+ * Clears all the output from the current line.
+ *
+ * @return $this
+ */
+ public function clearLine()
+ {
+ $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()
+ {
+ $this->output->write("\x1b[0J");
+ return $this;
+ }
+ /**
+ * Clears the entire screen.
+ *
+ * @return $this
+ */
+ public function clearScreen()
+ {
+ $this->output->write("\x1b[2J");
+ return $this;
+ }
+ /**
+ * Returns the current cursor position as x,y coordinates.
+ */
+ public function getCurrentPosition() : array
+ {
+ static $isTtySupported;
+ if (!($isTtySupported = $isTtySupported ?? '/' === \DIRECTORY_SEPARATOR && \stream_isatty(\STDOUT))) {
+ return [1, 1];
+ }
+ $sttyMode = \shell_exec('stty -g');
+ \shell_exec('stty -icanon -echo');
+ @\fwrite($this->input, "\x1b[6n");
+ $code = \trim(\fread($this->input, 1024));
+ \shell_exec(\sprintf('stty %s', $sttyMode));
+ \sscanf($code, "\x1b[%d;%dR", $row, $col);
+ return [$col, $row];
+ }
+}
diff --git a/vendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php b/vendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php
new file mode 100644
index 00000000..11537dcb
--- /dev/null
+++ b/vendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php
@@ -0,0 +1,107 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\DependencyInjection;
+
+use ClassLeak202307\Symfony\Component\Console\Command\Command;
+use ClassLeak202307\Symfony\Component\Console\Command\LazyCommand;
+use ClassLeak202307\Symfony\Component\Console\CommandLoader\ContainerCommandLoader;
+use ClassLeak202307\Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
+use ClassLeak202307\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use ClassLeak202307\Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
+use ClassLeak202307\Symfony\Component\DependencyInjection\ContainerBuilder;
+use ClassLeak202307\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+use ClassLeak202307\Symfony\Component\DependencyInjection\Reference;
+use ClassLeak202307\Symfony\Component\DependencyInjection\TypedReference;
+/**
+ * Registers console commands.
+ *
+ * @author Grégoire Pineau
+ */
+class AddConsoleCommandPass implements CompilerPassInterface
+{
+ /**
+ * @return void
+ */
+ public function process(ContainerBuilder $container)
+ {
+ $commandServices = $container->findTaggedServiceIds('console.command', \true);
+ $lazyCommandMap = [];
+ $lazyCommandRefs = [];
+ $serviceIds = [];
+ foreach ($commandServices as $id => $tags) {
+ $definition = $container->getDefinition($id);
+ $definition->addTag('container.no_preload');
+ $class = $container->getParameterBag()->resolveValue($definition->getClass());
+ 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() ?? '');
+ }
+ $aliases = \explode('|', $aliases ?? '');
+ $commandName = \array_shift($aliases);
+ if ($isHidden = '' === $commandName) {
+ $commandName = \array_shift($aliases);
+ }
+ 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);
+ }
+}
diff --git a/vendor/symfony/console/Descriptor/ApplicationDescription.php b/vendor/symfony/console/Descriptor/ApplicationDescription.php
new file mode 100644
index 00000000..48dfaecf
--- /dev/null
+++ b/vendor/symfony/console/Descriptor/ApplicationDescription.php
@@ -0,0 +1,129 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Descriptor;
+
+use ClassLeak202307\Symfony\Component\Console\Application;
+use ClassLeak202307\Symfony\Component\Console\Command\Command;
+use ClassLeak202307\Symfony\Component\Console\Exception\CommandNotFoundException;
+/**
+ * @author Jean-François Simon
+ *
+ * @internal
+ */
+class ApplicationDescription
+{
+ public const GLOBAL_NAMESPACE = '_global';
+ /**
+ * @var \Symfony\Component\Console\Application
+ */
+ private $application;
+ /**
+ * @var string|null
+ */
+ private $namespace;
+ /**
+ * @var bool
+ */
+ private $showHidden;
+ /**
+ * @var mixed[]
+ */
+ private $namespaces;
+ /**
+ * @var array
+ */
+ private $commands;
+ /**
+ * @var array
+ */
+ private $aliases = [];
+ public function __construct(Application $application, string $namespace = null, bool $showHidden = \false)
+ {
+ $this->application = $application;
+ $this->namespace = $namespace;
+ $this->showHidden = $showHidden;
+ }
+ public function getNamespaces() : array
+ {
+ if (!isset($this->namespaces)) {
+ $this->inspectApplication();
+ }
+ return $this->namespaces;
+ }
+ /**
+ * @return Command[]
+ */
+ public function getCommands() : array
+ {
+ if (!isset($this->commands)) {
+ $this->inspectApplication();
+ }
+ return $this->commands;
+ }
+ /**
+ * @throws CommandNotFoundException
+ */
+ 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));
+ }
+ return $this->commands[$name] ?? $this->aliases[$name];
+ }
+ private function inspectApplication() : void
+ {
+ $this->commands = [];
+ $this->namespaces = [];
+ $all = $this->application->all($this->namespace ? $this->application->findNamespace($this->namespace) : null);
+ foreach ($this->sortCommands($all) as $namespace => $commands) {
+ $names = [];
+ /** @var Command $command */
+ foreach ($commands as $name => $command) {
+ if (!$command->getName() || !$this->showHidden && $command->isHidden()) {
+ continue;
+ }
+ if ($command->getName() === $name) {
+ $this->commands[$name] = $command;
+ } else {
+ $this->aliases[$name] = $command;
+ }
+ $names[] = $name;
+ }
+ $this->namespaces[$namespace] = ['id' => $namespace, 'commands' => $names];
+ }
+ }
+ private function sortCommands(array $commands) : array
+ {
+ $namespacedCommands = [];
+ $globalCommands = [];
+ $sortedCommands = [];
+ foreach ($commands as $name => $command) {
+ $key = $this->application->extractNamespace($name, 1);
+ if (\in_array($key, ['', self::GLOBAL_NAMESPACE], \true)) {
+ $globalCommands[$name] = $command;
+ } else {
+ $namespacedCommands[$key][$name] = $command;
+ }
+ }
+ if ($globalCommands) {
+ \ksort($globalCommands);
+ $sortedCommands[self::GLOBAL_NAMESPACE] = $globalCommands;
+ }
+ if ($namespacedCommands) {
+ \ksort($namespacedCommands, \SORT_STRING);
+ foreach ($namespacedCommands as $key => $commandsSet) {
+ \ksort($commandsSet);
+ $sortedCommands[$key] = $commandsSet;
+ }
+ }
+ return $sortedCommands;
+ }
+}
diff --git a/vendor/symfony/console/Descriptor/Descriptor.php b/vendor/symfony/console/Descriptor/Descriptor.php
new file mode 100644
index 00000000..732efda5
--- /dev/null
+++ b/vendor/symfony/console/Descriptor/Descriptor.php
@@ -0,0 +1,78 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Descriptor;
+
+use ClassLeak202307\Symfony\Component\Console\Application;
+use ClassLeak202307\Symfony\Component\Console\Command\Command;
+use ClassLeak202307\Symfony\Component\Console\Exception\InvalidArgumentException;
+use ClassLeak202307\Symfony\Component\Console\Input\InputArgument;
+use ClassLeak202307\Symfony\Component\Console\Input\InputDefinition;
+use ClassLeak202307\Symfony\Component\Console\Input\InputOption;
+use ClassLeak202307\Symfony\Component\Console\Output\OutputInterface;
+/**
+ * @author Jean-François Simon
+ *
+ * @internal
+ */
+abstract class Descriptor implements DescriptorInterface
+{
+ /**
+ * @var \Symfony\Component\Console\Output\OutputInterface
+ */
+ protected $output;
+ public function describe(OutputInterface $output, object $object, array $options = []) : void
+ {
+ $this->output = $output;
+ switch (\true) {
+ case $object instanceof InputArgument:
+ $this->describeInputArgument($object, $options);
+ break;
+ case $object instanceof InputOption:
+ $this->describeInputOption($object, $options);
+ break;
+ case $object instanceof InputDefinition:
+ $this->describeInputDefinition($object, $options);
+ break;
+ case $object instanceof Command:
+ $this->describeCommand($object, $options);
+ break;
+ case $object instanceof Application:
+ $this->describeApplication($object, $options);
+ break;
+ default:
+ throw new InvalidArgumentException(\sprintf('Object of type "%s" is not describable.', \get_debug_type($object)));
+ }
+ }
+ protected function write(string $content, bool $decorated = \false) : void
+ {
+ $this->output->write($content, \false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW);
+ }
+ /**
+ * Describes an InputArgument instance.
+ */
+ protected abstract function describeInputArgument(InputArgument $argument, array $options = []) : void;
+ /**
+ * Describes an InputOption instance.
+ */
+ protected abstract function describeInputOption(InputOption $option, array $options = []) : void;
+ /**
+ * Describes an InputDefinition instance.
+ */
+ protected abstract function describeInputDefinition(InputDefinition $definition, array $options = []) : void;
+ /**
+ * Describes a Command instance.
+ */
+ protected abstract function describeCommand(Command $command, array $options = []) : void;
+ /**
+ * Describes an Application instance.
+ */
+ protected abstract function describeApplication(Application $application, array $options = []) : void;
+}
diff --git a/vendor/symfony/console/Descriptor/DescriptorInterface.php b/vendor/symfony/console/Descriptor/DescriptorInterface.php
new file mode 100644
index 00000000..daaa0734
--- /dev/null
+++ b/vendor/symfony/console/Descriptor/DescriptorInterface.php
@@ -0,0 +1,25 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Descriptor;
+
+use ClassLeak202307\Symfony\Component\Console\Output\OutputInterface;
+/**
+ * Descriptor interface.
+ *
+ * @author Jean-François Simon
+ */
+interface DescriptorInterface
+{
+ /**
+ * @return void
+ */
+ public function describe(OutputInterface $output, object $object, array $options = []);
+}
diff --git a/vendor/symfony/console/Descriptor/JsonDescriptor.php b/vendor/symfony/console/Descriptor/JsonDescriptor.php
new file mode 100644
index 00000000..8d73fe7f
--- /dev/null
+++ b/vendor/symfony/console/Descriptor/JsonDescriptor.php
@@ -0,0 +1,112 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Descriptor;
+
+use ClassLeak202307\Symfony\Component\Console\Application;
+use ClassLeak202307\Symfony\Component\Console\Command\Command;
+use ClassLeak202307\Symfony\Component\Console\Input\InputArgument;
+use ClassLeak202307\Symfony\Component\Console\Input\InputDefinition;
+use ClassLeak202307\Symfony\Component\Console\Input\InputOption;
+/**
+ * JSON descriptor.
+ *
+ * @author Jean-François Simon
+ *
+ * @internal
+ */
+class JsonDescriptor extends Descriptor
+{
+ protected function describeInputArgument(InputArgument $argument, array $options = []) : void
+ {
+ $this->writeData($this->getInputArgumentData($argument), $options);
+ }
+ protected function describeInputOption(InputOption $option, array $options = []) : void
+ {
+ $this->writeData($this->getInputOptionData($option), $options);
+ if ($option->isNegatable()) {
+ $this->writeData($this->getInputOptionData($option, \true), $options);
+ }
+ }
+ protected function describeInputDefinition(InputDefinition $definition, array $options = []) : void
+ {
+ $this->writeData($this->getInputDefinitionData($definition), $options);
+ }
+ protected function describeCommand(Command $command, array $options = []) : void
+ {
+ $this->writeData($this->getCommandData($command, $options['short'] ?? \false), $options);
+ }
+ protected function describeApplication(Application $application, array $options = []) : void
+ {
+ $describedNamespace = $options['namespace'] ?? null;
+ $description = new ApplicationDescription($application, $describedNamespace, \true);
+ $commands = [];
+ foreach ($description->getCommands() as $command) {
+ $commands[] = $this->getCommandData($command, $options['short'] ?? \false);
+ }
+ $data = [];
+ if ('UNKNOWN' !== $application->getName()) {
+ $data['application']['name'] = $application->getName();
+ if ('UNKNOWN' !== $application->getVersion()) {
+ $data['application']['version'] = $application->getVersion();
+ }
+ }
+ $data['commands'] = $commands;
+ if ($describedNamespace) {
+ $data['namespace'] = $describedNamespace;
+ } else {
+ $data['namespaces'] = \array_values($description->getNamespaces());
+ }
+ $this->writeData($data, $options);
+ }
+ /**
+ * Writes data as json.
+ */
+ private function writeData(array $data, array $options) : void
+ {
+ $flags = $options['json_encoding'] ?? 0;
+ $this->write(\json_encode($data, $flags));
+ }
+ private function getInputArgumentData(InputArgument $argument) : 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()];
+ }
+ private function getInputOptionData(InputOption $option, bool $negated = \false) : 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() ? '-' . \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()];
+ }
+ private function getInputDefinitionData(InputDefinition $definition) : array
+ {
+ $inputArguments = [];
+ foreach ($definition->getArguments() as $name => $argument) {
+ $inputArguments[$name] = $this->getInputArgumentData($argument);
+ }
+ $inputOptions = [];
+ foreach ($definition->getOptions() as $name => $option) {
+ $inputOptions[$name] = $this->getInputOptionData($option);
+ if ($option->isNegatable()) {
+ $inputOptions['no-' . $name] = $this->getInputOptionData($option, \true);
+ }
+ }
+ return ['arguments' => $inputArguments, 'options' => $inputOptions];
+ }
+ private function getCommandData(Command $command, bool $short = \false) : array
+ {
+ $data = ['name' => $command->getName(), 'description' => $command->getDescription()];
+ 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;
+ }
+}
diff --git a/vendor/symfony/console/Descriptor/MarkdownDescriptor.php b/vendor/symfony/console/Descriptor/MarkdownDescriptor.php
new file mode 100644
index 00000000..915f7e48
--- /dev/null
+++ b/vendor/symfony/console/Descriptor/MarkdownDescriptor.php
@@ -0,0 +1,128 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Descriptor;
+
+use ClassLeak202307\Symfony\Component\Console\Application;
+use ClassLeak202307\Symfony\Component\Console\Command\Command;
+use ClassLeak202307\Symfony\Component\Console\Helper\Helper;
+use ClassLeak202307\Symfony\Component\Console\Input\InputArgument;
+use ClassLeak202307\Symfony\Component\Console\Input\InputDefinition;
+use ClassLeak202307\Symfony\Component\Console\Input\InputOption;
+use ClassLeak202307\Symfony\Component\Console\Output\OutputInterface;
+/**
+ * Markdown descriptor.
+ *
+ * @author Jean-François Simon
+ *
+ * @internal
+ */
+class MarkdownDescriptor extends Descriptor
+{
+ public function describe(OutputInterface $output, object $object, array $options = []) : void
+ {
+ $decorated = $output->isDecorated();
+ $output->setDecorated(\false);
+ parent::describe($output, $object, $options);
+ $output->setDecorated($decorated);
+ }
+ protected function write(string $content, bool $decorated = \true) : void
+ {
+ parent::write($content, $decorated);
+ }
+ protected function describeInputArgument(InputArgument $argument, array $options = []) : void
+ {
+ $this->write('#### `' . ($argument->getName() ?: '') . "`\n\n" . ($argument->getDescription() ? \preg_replace('/\\s*[\\r\\n]\\s*/', "\n", $argument->getDescription()) . "\n\n" : '') . '* Is required: ' . ($argument->isRequired() ? 'yes' : 'no') . "\n" . '* Is array: ' . ($argument->isArray() ? 'yes' : 'no') . "\n" . '* Default: `' . \str_replace("\n", '', \var_export($argument->getDefault(), \true)) . '`');
+ }
+ protected function describeInputOption(InputOption $option, array $options = []) : void
+ {
+ $name = '--' . $option->getName();
+ if ($option->isNegatable()) {
+ $name .= '|--no-' . $option->getName();
+ }
+ if ($option->getShortcut()) {
+ $name .= '|-' . \str_replace('|', '|-', $option->getShortcut()) . '';
+ }
+ $this->write('#### `' . $name . '`' . "\n\n" . ($option->getDescription() ? \preg_replace('/\\s*[\\r\\n]\\s*/', "\n", $option->getDescription()) . "\n\n" : '') . '* 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)) . '`');
+ }
+ protected function describeInputDefinition(InputDefinition $definition, array $options = []) : void
+ {
+ if ($showArguments = \count($definition->getArguments()) > 0) {
+ $this->write('### Arguments');
+ foreach ($definition->getArguments() as $argument) {
+ $this->write("\n\n");
+ $this->describeInputArgument($argument);
+ }
+ }
+ if (\count($definition->getOptions()) > 0) {
+ if ($showArguments) {
+ $this->write("\n\n");
+ }
+ $this->write('### Options');
+ foreach ($definition->getOptions() as $option) {
+ $this->write("\n\n");
+ $this->describeInputOption($option);
+ }
+ }
+ }
+ protected function describeCommand(Command $command, array $options = []) : void
+ {
+ 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::width($command->getName()) + 2) . "\n\n" . ($command->getDescription() ? $command->getDescription() . "\n\n" : '') . '### Usage' . "\n\n" . \array_reduce(\array_merge([$command->getSynopsis()], $command->getAliases(), $command->getUsages()), function ($carry, $usage) {
+ return $carry . '* `' . $usage . '`' . "\n";
+ }));
+ if ($help = $command->getProcessedHelp()) {
+ $this->write("\n");
+ $this->write($help);
+ }
+ $definition = $command->getDefinition();
+ if ($definition->getOptions() || $definition->getArguments()) {
+ $this->write("\n\n");
+ $this->describeInputDefinition($definition);
+ }
+ }
+ protected function describeApplication(Application $application, array $options = []) : void
+ {
+ $describedNamespace = $options['namespace'] ?? null;
+ $description = new ApplicationDescription($application, $describedNamespace);
+ $title = $this->getApplicationTitle($application);
+ $this->write($title . "\n" . \str_repeat('=', Helper::width($title)));
+ foreach ($description->getNamespaces() as $namespace) {
+ if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
+ $this->write("\n\n");
+ $this->write('**' . $namespace['id'] . ':**');
+ }
+ $this->write("\n\n");
+ $this->write(\implode("\n", \array_map(function ($commandName) use($description) {
+ return \sprintf('* [`%s`](#%s)', $commandName, \str_replace(':', '', $description->getCommand($commandName)->getName()));
+ }, $namespace['commands'])));
+ }
+ foreach ($description->getCommands() as $command) {
+ $this->write("\n\n");
+ $this->describeCommand($command, $options);
+ }
+ }
+ private function getApplicationTitle(Application $application) : string
+ {
+ if ('UNKNOWN' !== $application->getName()) {
+ if ('UNKNOWN' !== $application->getVersion()) {
+ return \sprintf('%s %s', $application->getName(), $application->getVersion());
+ }
+ return $application->getName();
+ }
+ return 'Console Tool';
+ }
+}
diff --git a/vendor/symfony/console/Descriptor/ReStructuredTextDescriptor.php b/vendor/symfony/console/Descriptor/ReStructuredTextDescriptor.php
new file mode 100644
index 00000000..0e860b2e
--- /dev/null
+++ b/vendor/symfony/console/Descriptor/ReStructuredTextDescriptor.php
@@ -0,0 +1,234 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Descriptor;
+
+use ClassLeak202307\Symfony\Component\Console\Application;
+use ClassLeak202307\Symfony\Component\Console\Command\Command;
+use ClassLeak202307\Symfony\Component\Console\Helper\Helper;
+use ClassLeak202307\Symfony\Component\Console\Input\InputArgument;
+use ClassLeak202307\Symfony\Component\Console\Input\InputDefinition;
+use ClassLeak202307\Symfony\Component\Console\Input\InputOption;
+use ClassLeak202307\Symfony\Component\Console\Output\OutputInterface;
+use ClassLeak202307\Symfony\Component\String\UnicodeString;
+class ReStructuredTextDescriptor extends Descriptor
+{
+ //
+ /**
+ * @var string
+ */
+ private $partChar = '=';
+ //
+ /**
+ * @var string
+ */
+ private $chapterChar = '-';
+ //
+ /**
+ * @var string
+ */
+ private $sectionChar = '~';
+ //
+ /**
+ * @var string
+ */
+ private $subsectionChar = '.';
+ //
+ /**
+ * @var string
+ */
+ private $subsubsectionChar = '^';
+ //
+ /**
+ * @var string
+ */
+ private $paragraphsChar = '"';
+ /**
+ * @var mixed[]
+ */
+ private $visibleNamespaces = [];
+ public function describe(OutputInterface $output, object $object, array $options = []) : void
+ {
+ $decorated = $output->isDecorated();
+ $output->setDecorated(\false);
+ parent::describe($output, $object, $options);
+ $output->setDecorated($decorated);
+ }
+ /**
+ * Override parent method to set $decorated = true.
+ */
+ protected function write(string $content, bool $decorated = \true) : void
+ {
+ parent::write($content, $decorated);
+ }
+ protected function describeInputArgument(InputArgument $argument, array $options = []) : void
+ {
+ $this->write($argument->getName() ?: '' . "\n" . \str_repeat($this->paragraphsChar, Helper::width($argument->getName())) . "\n\n" . ($argument->getDescription() ? \preg_replace('/\\s*[\\r\\n]\\s*/', "\n", $argument->getDescription()) . "\n\n" : '') . '- **Is required**: ' . ($argument->isRequired() ? 'yes' : 'no') . "\n" . '- **Is array**: ' . ($argument->isArray() ? 'yes' : 'no') . "\n" . '- **Default**: ``' . \str_replace("\n", '', \var_export($argument->getDefault(), \true)) . '``');
+ }
+ protected function describeInputOption(InputOption $option, array $options = []) : void
+ {
+ $name = '\\-\\-' . $option->getName();
+ if ($option->isNegatable()) {
+ $name .= '|\\-\\-no-' . $option->getName();
+ }
+ if ($option->getShortcut()) {
+ $name .= '|-' . \str_replace('|', '|-', $option->getShortcut());
+ }
+ $optionDescription = $option->getDescription() ? \preg_replace('/\\s*[\\r\\n]\\s*/', "\n\n", $option->getDescription()) . "\n\n" : '';
+ $optionDescription = (new UnicodeString($optionDescription))->ascii();
+ $this->write($name . "\n" . \str_repeat($this->paragraphsChar, Helper::width($name)) . "\n\n" . $optionDescription . '- **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)) . '``' . "\n");
+ }
+ protected function describeInputDefinition(InputDefinition $definition, array $options = []) : void
+ {
+ if ($showArguments = (bool) $definition->getArguments()) {
+ $this->write("Arguments\n" . \str_repeat($this->subsubsectionChar, 9)) . "\n\n";
+ foreach ($definition->getArguments() as $argument) {
+ $this->write("\n\n");
+ $this->describeInputArgument($argument);
+ }
+ }
+ if ($nonDefaultOptions = $this->getNonDefaultOptions($definition)) {
+ if ($showArguments) {
+ $this->write("\n\n");
+ }
+ $this->write("Options\n" . \str_repeat($this->subsubsectionChar, 7) . "\n\n");
+ foreach ($nonDefaultOptions as $option) {
+ $this->describeInputOption($option);
+ $this->write("\n");
+ }
+ }
+ }
+ protected function describeCommand(Command $command, array $options = []) : void
+ {
+ if ($options['short'] ?? \false) {
+ $this->write('``' . $command->getName() . "``\n" . \str_repeat($this->subsectionChar, Helper::width($command->getName())) . "\n\n" . ($command->getDescription() ? $command->getDescription() . "\n\n" : '') . "Usage\n" . \str_repeat($this->paragraphsChar, 5) . "\n\n" . \array_reduce($command->getAliases(), static function ($carry, $usage) {
+ return $carry . '- ``' . $usage . '``' . "\n";
+ }));
+ return;
+ }
+ $command->mergeApplicationDefinition(\false);
+ foreach ($command->getAliases() as $alias) {
+ $this->write('.. _' . $alias . ":\n\n");
+ }
+ $this->write($command->getName() . "\n" . \str_repeat($this->subsectionChar, Helper::width($command->getName())) . "\n\n" . ($command->getDescription() ? $command->getDescription() . "\n\n" : '') . "Usage\n" . \str_repeat($this->subsubsectionChar, 5) . "\n\n" . \array_reduce(\array_merge([$command->getSynopsis()], $command->getAliases(), $command->getUsages()), static function ($carry, $usage) {
+ return $carry . '- ``' . $usage . '``' . "\n";
+ }));
+ if ($help = $command->getProcessedHelp()) {
+ $this->write("\n");
+ $this->write($help);
+ }
+ $definition = $command->getDefinition();
+ if ($definition->getOptions() || $definition->getArguments()) {
+ $this->write("\n\n");
+ $this->describeInputDefinition($definition);
+ }
+ }
+ protected function describeApplication(Application $application, array $options = []) : void
+ {
+ $description = new ApplicationDescription($application, $options['namespace'] ?? null);
+ $title = $this->getApplicationTitle($application);
+ $this->write($title . "\n" . \str_repeat($this->partChar, Helper::width($title)));
+ $this->createTableOfContents($description, $application);
+ $this->describeCommands($application, $options);
+ }
+ private function getApplicationTitle(Application $application) : string
+ {
+ if ('UNKNOWN' === $application->getName()) {
+ return 'Console Tool';
+ }
+ if ('UNKNOWN' !== $application->getVersion()) {
+ return \sprintf('%s %s', $application->getName(), $application->getVersion());
+ }
+ return $application->getName();
+ }
+ private function describeCommands($application, array $options) : void
+ {
+ $title = 'Commands';
+ $this->write("\n\n{$title}\n" . \str_repeat($this->chapterChar, Helper::width($title)) . "\n\n");
+ foreach ($this->visibleNamespaces as $namespace) {
+ if ('_global' === $namespace) {
+ $commands = $application->all('');
+ $this->write('Global' . "\n" . \str_repeat($this->sectionChar, Helper::width('Global')) . "\n\n");
+ } else {
+ $commands = $application->all($namespace);
+ $this->write($namespace . "\n" . \str_repeat($this->sectionChar, Helper::width($namespace)) . "\n\n");
+ }
+ foreach ($this->removeAliasesAndHiddenCommands($commands) as $command) {
+ $this->describeCommand($command, $options);
+ $this->write("\n\n");
+ }
+ }
+ }
+ private function createTableOfContents(ApplicationDescription $description, Application $application) : void
+ {
+ $this->setVisibleNamespaces($description);
+ $chapterTitle = 'Table of Contents';
+ $this->write("\n\n{$chapterTitle}\n" . \str_repeat($this->chapterChar, Helper::width($chapterTitle)) . "\n\n");
+ foreach ($this->visibleNamespaces as $namespace) {
+ if ('_global' === $namespace) {
+ $commands = $application->all('');
+ } else {
+ $commands = $application->all($namespace);
+ $this->write("\n\n");
+ $this->write($namespace . "\n" . \str_repeat($this->sectionChar, Helper::width($namespace)) . "\n\n");
+ }
+ $commands = $this->removeAliasesAndHiddenCommands($commands);
+ $this->write("\n\n");
+ $this->write(\implode("\n", \array_map(static function ($commandName) {
+ return \sprintf('- `%s`_', $commandName);
+ }, \array_keys($commands))));
+ }
+ }
+ private function getNonDefaultOptions(InputDefinition $definition) : array
+ {
+ $globalOptions = ['help', 'quiet', 'verbose', 'version', 'ansi', 'no-interaction'];
+ $nonDefaultOptions = [];
+ foreach ($definition->getOptions() as $option) {
+ // Skip global options.
+ if (!\in_array($option->getName(), $globalOptions)) {
+ $nonDefaultOptions[] = $option;
+ }
+ }
+ return $nonDefaultOptions;
+ }
+ private function setVisibleNamespaces(ApplicationDescription $description) : void
+ {
+ $commands = $description->getCommands();
+ foreach ($description->getNamespaces() as $namespace) {
+ try {
+ $namespaceCommands = $namespace['commands'];
+ foreach ($namespaceCommands as $key => $commandName) {
+ if (!\array_key_exists($commandName, $commands)) {
+ // If the array key does not exist, then this is an alias.
+ unset($namespaceCommands[$key]);
+ } elseif ($commands[$commandName]->isHidden()) {
+ unset($namespaceCommands[$key]);
+ }
+ }
+ if (!$namespaceCommands) {
+ // If the namespace contained only aliases or hidden commands, skip the namespace.
+ continue;
+ }
+ } catch (\Exception $exception) {
+ }
+ $this->visibleNamespaces[] = $namespace['id'];
+ }
+ }
+ private function removeAliasesAndHiddenCommands(array $commands) : array
+ {
+ foreach ($commands as $key => $command) {
+ if ($command->isHidden() || \in_array($key, $command->getAliases(), \true)) {
+ unset($commands[$key]);
+ }
+ }
+ unset($commands['completion']);
+ return $commands;
+ }
+}
diff --git a/vendor/symfony/console/Descriptor/TextDescriptor.php b/vendor/symfony/console/Descriptor/TextDescriptor.php
new file mode 100644
index 00000000..42561409
--- /dev/null
+++ b/vendor/symfony/console/Descriptor/TextDescriptor.php
@@ -0,0 +1,274 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Descriptor;
+
+use ClassLeak202307\Symfony\Component\Console\Application;
+use ClassLeak202307\Symfony\Component\Console\Command\Command;
+use ClassLeak202307\Symfony\Component\Console\Formatter\OutputFormatter;
+use ClassLeak202307\Symfony\Component\Console\Helper\Helper;
+use ClassLeak202307\Symfony\Component\Console\Input\InputArgument;
+use ClassLeak202307\Symfony\Component\Console\Input\InputDefinition;
+use ClassLeak202307\Symfony\Component\Console\Input\InputOption;
+/**
+ * Text descriptor.
+ *
+ * @author Jean-François Simon
+ *
+ * @internal
+ */
+class TextDescriptor extends Descriptor
+{
+ protected function describeInputArgument(InputArgument $argument, array $options = []) : void
+ {
+ if (null !== $argument->getDefault() && (!\is_array($argument->getDefault()) || \count($argument->getDefault()))) {
+ $default = \sprintf(' [default: %s]', $this->formatDefaultValue($argument->getDefault()));
+ } else {
+ $default = '';
+ }
+ $totalWidth = $options['total_width'] ?? Helper::width($argument->getName());
+ $spacingWidth = $totalWidth - \strlen($argument->getName());
+ $this->writeText(\sprintf(
+ ' %s %s%s%s',
+ $argument->getName(),
+ \str_repeat(' ', $spacingWidth),
+ // + 4 = 2 spaces before , 2 spaces after
+ \preg_replace('/\\s*[\\r\\n]\\s*/', "\n" . \str_repeat(' ', $totalWidth + 4), $argument->getDescription()),
+ $default
+ ), $options);
+ }
+ protected function describeInputOption(InputOption $option, array $options = []) : void
+ {
+ if ($option->acceptValue() && null !== $option->getDefault() && (!\is_array($option->getDefault()) || \count($option->getDefault()))) {
+ $default = \sprintf(' [default: %s]', $this->formatDefaultValue($option->getDefault()));
+ } else {
+ $default = '';
+ }
+ $value = '';
+ if ($option->acceptValue()) {
+ $value = '=' . \strtoupper($option->getName());
+ if ($option->isValueOptional()) {
+ $value = '[' . $value . ']';
+ }
+ }
+ $totalWidth = $options['total_width'] ?? $this->calculateTotalWidthForOptions([$option]);
+ $synopsis = \sprintf('%s%s', $option->getShortcut() ? \sprintf('-%s, ', $option->getShortcut()) : ' ', \sprintf($option->isNegatable() ? '--%1$s|--no-%1$s' : '--%1$s%2$s', $option->getName(), $value));
+ $spacingWidth = $totalWidth - Helper::width($synopsis);
+ $this->writeText(\sprintf(
+ ' %s %s%s%s%s',
+ $synopsis,
+ \str_repeat(' ', $spacingWidth),
+ // + 4 = 2 spaces before , 2 spaces after
+ \preg_replace('/\\s*[\\r\\n]\\s*/', "\n" . \str_repeat(' ', $totalWidth + 4), $option->getDescription()),
+ $default,
+ $option->isArray() ? ' (multiple values allowed)' : ''
+ ), $options);
+ }
+ protected function describeInputDefinition(InputDefinition $definition, array $options = []) : void
+ {
+ $totalWidth = $this->calculateTotalWidthForOptions($definition->getOptions());
+ foreach ($definition->getArguments() as $argument) {
+ $totalWidth = \max($totalWidth, Helper::width($argument->getName()));
+ }
+ if ($definition->getArguments()) {
+ $this->writeText('Arguments:', $options);
+ $this->writeText("\n");
+ foreach ($definition->getArguments() as $argument) {
+ $this->describeInputArgument($argument, \array_merge($options, ['total_width' => $totalWidth]));
+ $this->writeText("\n");
+ }
+ }
+ if ($definition->getArguments() && $definition->getOptions()) {
+ $this->writeText("\n");
+ }
+ if ($definition->getOptions()) {
+ $laterOptions = [];
+ $this->writeText('Options:', $options);
+ foreach ($definition->getOptions() as $option) {
+ if (\strlen($option->getShortcut() ?? '') > 1) {
+ $laterOptions[] = $option;
+ continue;
+ }
+ $this->writeText("\n");
+ $this->describeInputOption($option, \array_merge($options, ['total_width' => $totalWidth]));
+ }
+ foreach ($laterOptions as $option) {
+ $this->writeText("\n");
+ $this->describeInputOption($option, \array_merge($options, ['total_width' => $totalWidth]));
+ }
+ }
+ }
+ protected function describeCommand(Command $command, array $options = []) : void
+ {
+ $command->mergeApplicationDefinition(\false);
+ if ($description = $command->getDescription()) {
+ $this->writeText('Description:', $options);
+ $this->writeText("\n");
+ $this->writeText(' ' . $description);
+ $this->writeText("\n\n");
+ }
+ $this->writeText('Usage:', $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->getDefinition();
+ if ($definition->getOptions() || $definition->getArguments()) {
+ $this->writeText("\n");
+ $this->describeInputDefinition($definition, $options);
+ $this->writeText("\n");
+ }
+ $help = $command->getProcessedHelp();
+ if ($help && $help !== $description) {
+ $this->writeText("\n");
+ $this->writeText('Help:', $options);
+ $this->writeText("\n");
+ $this->writeText(' ' . \str_replace("\n", "\n ", $help), $options);
+ $this->writeText("\n");
+ }
+ }
+ protected function describeApplication(Application $application, array $options = []) : void
+ {
+ $describedNamespace = $options['namespace'] ?? null;
+ $description = new ApplicationDescription($application, $describedNamespace);
+ if (isset($options['raw_text']) && $options['raw_text']) {
+ $width = $this->getColumnWidth($description->getCommands());
+ foreach ($description->getCommands() as $command) {
+ $this->writeText(\sprintf("%-{$width}s %s", $command->getName(), $command->getDescription()), $options);
+ $this->writeText("\n");
+ }
+ } else {
+ if ('' != ($help = $application->getHelp())) {
+ $this->writeText("{$help}\n\n", $options);
+ }
+ $this->writeText("Usage:\n", $options);
+ $this->writeText(" command [options] [arguments]\n\n", $options);
+ $this->describeInputDefinition(new InputDefinition($application->getDefinition()->getOptions()), $options);
+ $this->writeText("\n");
+ $this->writeText("\n");
+ $commands = $description->getCommands();
+ $namespaces = $description->getNamespaces();
+ if ($describedNamespace && $namespaces) {
+ // make sure all alias commands are included when describing a specific namespace
+ $describedNamespaceInfo = \reset($namespaces);
+ foreach ($describedNamespaceInfo['commands'] as $name) {
+ $commands[$name] = $description->getCommand($name);
+ }
+ }
+ // calculate max. width based on available commands per namespace
+ $width = $this->getColumnWidth(\array_merge(...\array_values(\array_map(function ($namespace) use($commands) {
+ return \array_intersect($namespace['commands'], \array_keys($commands));
+ }, \array_values($namespaces)))));
+ if ($describedNamespace) {
+ $this->writeText(\sprintf('Available commands for the "%s" namespace:', $describedNamespace), $options);
+ } else {
+ $this->writeText('Available commands:', $options);
+ }
+ foreach ($namespaces as $namespace) {
+ $namespace['commands'] = \array_filter($namespace['commands'], function ($name) use($commands) {
+ return isset($commands[$name]);
+ });
+ if (!$namespace['commands']) {
+ continue;
+ }
+ if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
+ $this->writeText("\n");
+ $this->writeText(' ' . $namespace['id'] . '', $options);
+ }
+ foreach ($namespace['commands'] as $name) {
+ $this->writeText("\n");
+ $spacingWidth = $width - Helper::width($name);
+ $command = $commands[$name];
+ $commandAliases = $name === $command->getName() ? $this->getCommandAliasesText($command) : '';
+ $this->writeText(\sprintf(' %s%s%s', $name, \str_repeat(' ', $spacingWidth), $commandAliases . $command->getDescription()), $options);
+ }
+ }
+ $this->writeText("\n");
+ }
+ }
+ private function writeText(string $content, array $options = []) : void
+ {
+ $this->write(isset($options['raw_text']) && $options['raw_text'] ? \strip_tags($content) : $content, isset($options['raw_output']) ? !$options['raw_output'] : \true);
+ }
+ /**
+ * Formats command aliases to show them in the command description.
+ */
+ private function getCommandAliasesText(Command $command) : string
+ {
+ $text = '';
+ $aliases = $command->getAliases();
+ if ($aliases) {
+ $text = '[' . \implode('|', $aliases) . '] ';
+ }
+ return $text;
+ }
+ /**
+ * Formats input option/argument default value.
+ * @param mixed $default
+ */
+ private function formatDefaultValue($default) : string
+ {
+ if (\INF === $default) {
+ return 'INF';
+ }
+ if (\is_string($default)) {
+ $default = OutputFormatter::escape($default);
+ } elseif (\is_array($default)) {
+ foreach ($default as $key => $value) {
+ if (\is_string($value)) {
+ $default[$key] = OutputFormatter::escape($value);
+ }
+ }
+ }
+ return \str_replace('\\\\', '\\', \json_encode($default, \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE));
+ }
+ /**
+ * @param array $commands
+ */
+ private function getColumnWidth(array $commands) : int
+ {
+ $widths = [];
+ foreach ($commands as $command) {
+ if ($command instanceof Command) {
+ $widths[] = Helper::width($command->getName());
+ foreach ($command->getAliases() as $alias) {
+ $widths[] = Helper::width($alias);
+ }
+ } else {
+ $widths[] = Helper::width($command);
+ }
+ }
+ return $widths ? \max($widths) + 2 : 0;
+ }
+ /**
+ * @param InputOption[] $options
+ */
+ private function calculateTotalWidthForOptions(array $options) : int
+ {
+ $totalWidth = 0;
+ foreach ($options as $option) {
+ // "-" + shortcut + ", --" + name
+ $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;
+ }
+ $totalWidth = \max($totalWidth, $nameLength);
+ }
+ return $totalWidth;
+ }
+}
diff --git a/vendor/symfony/console/Descriptor/XmlDescriptor.php b/vendor/symfony/console/Descriptor/XmlDescriptor.php
new file mode 100644
index 00000000..221d0a78
--- /dev/null
+++ b/vendor/symfony/console/Descriptor/XmlDescriptor.php
@@ -0,0 +1,191 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Descriptor;
+
+use ClassLeak202307\Symfony\Component\Console\Application;
+use ClassLeak202307\Symfony\Component\Console\Command\Command;
+use ClassLeak202307\Symfony\Component\Console\Input\InputArgument;
+use ClassLeak202307\Symfony\Component\Console\Input\InputDefinition;
+use ClassLeak202307\Symfony\Component\Console\Input\InputOption;
+/**
+ * XML descriptor.
+ *
+ * @author Jean-François Simon
+ *
+ * @internal
+ */
+class XmlDescriptor extends Descriptor
+{
+ public function getInputDefinitionDocument(InputDefinition $definition) : \DOMDocument
+ {
+ $dom = new \DOMDocument('1.0', 'UTF-8');
+ $dom->appendChild($definitionXML = $dom->createElement('definition'));
+ $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments'));
+ foreach ($definition->getArguments() as $argument) {
+ $this->appendDocument($argumentsXML, $this->getInputArgumentDocument($argument));
+ }
+ $definitionXML->appendChild($optionsXML = $dom->createElement('options'));
+ foreach ($definition->getOptions() as $option) {
+ $this->appendDocument($optionsXML, $this->getInputOptionDocument($option));
+ }
+ return $dom;
+ }
+ public function getCommandDocument(Command $command, bool $short = \false) : \DOMDocument
+ {
+ $dom = new \DOMDocument('1.0', 'UTF-8');
+ $dom->appendChild($commandXML = $dom->createElement('command'));
+ $commandXML->setAttribute('id', $command->getName());
+ $commandXML->setAttribute('name', $command->getName());
+ $commandXML->setAttribute('hidden', $command->isHidden() ? 1 : 0);
+ $commandXML->appendChild($usagesXML = $dom->createElement('usages'));
+ $commandXML->appendChild($descriptionXML = $dom->createElement('description'));
+ $descriptionXML->appendChild($dom->createTextNode(\str_replace("\n", "\n ", $command->getDescription())));
+ if ($short) {
+ foreach ($command->getAliases() as $usage) {
+ $usagesXML->appendChild($dom->createElement('usage', $usage));
+ }
+ } else {
+ $command->mergeApplicationDefinition(\false);
+ 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;
+ }
+ 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 ('UNKNOWN' !== $application->getName()) {
+ $rootXml->setAttribute('name', $application->getName());
+ if ('UNKNOWN' !== $application->getVersion()) {
+ $rootXml->setAttribute('version', $application->getVersion());
+ }
+ }
+ $rootXml->appendChild($commandsXML = $dom->createElement('commands'));
+ $description = new ApplicationDescription($application, $namespace, \true);
+ if ($namespace) {
+ $commandsXML->setAttribute('namespace', $namespace);
+ }
+ foreach ($description->getCommands() as $command) {
+ $this->appendDocument($commandsXML, $this->getCommandDocument($command, $short));
+ }
+ if (!$namespace) {
+ $rootXml->appendChild($namespacesXML = $dom->createElement('namespaces'));
+ foreach ($description->getNamespaces() as $namespaceDescription) {
+ $namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace'));
+ $namespaceArrayXML->setAttribute('id', $namespaceDescription['id']);
+ foreach ($namespaceDescription['commands'] as $name) {
+ $namespaceArrayXML->appendChild($commandXML = $dom->createElement('command'));
+ $commandXML->appendChild($dom->createTextNode($name));
+ }
+ }
+ }
+ return $dom;
+ }
+ protected function describeInputArgument(InputArgument $argument, array $options = []) : void
+ {
+ $this->writeDocument($this->getInputArgumentDocument($argument));
+ }
+ protected function describeInputOption(InputOption $option, array $options = []) : void
+ {
+ $this->writeDocument($this->getInputOptionDocument($option));
+ }
+ protected function describeInputDefinition(InputDefinition $definition, array $options = []) : void
+ {
+ $this->writeDocument($this->getInputDefinitionDocument($definition));
+ }
+ protected function describeCommand(Command $command, array $options = []) : void
+ {
+ $this->writeDocument($this->getCommandDocument($command, $options['short'] ?? \false));
+ }
+ protected function describeApplication(Application $application, array $options = []) : void
+ {
+ $this->writeDocument($this->getApplicationDocument($application, $options['namespace'] ?? null, $options['short'] ?? \false));
+ }
+ /**
+ * Appends document children to parent node.
+ */
+ private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent) : void
+ {
+ foreach ($importedParent->childNodes as $childNode) {
+ $parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, \true));
+ }
+ }
+ /**
+ * Writes DOM document.
+ */
+ private function writeDocument(\DOMDocument $dom) : void
+ {
+ $dom->formatOutput = \true;
+ $this->write($dom->saveXML());
+ }
+ private function getInputArgumentDocument(InputArgument $argument) : \DOMDocument
+ {
+ $dom = new \DOMDocument('1.0', 'UTF-8');
+ $dom->appendChild($objectXML = $dom->createElement('argument'));
+ $objectXML->setAttribute('name', $argument->getName());
+ $objectXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0);
+ $objectXML->setAttribute('is_array', $argument->isArray() ? 1 : 0);
+ $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
+ $descriptionXML->appendChild($dom->createTextNode($argument->getDescription()));
+ $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
+ $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));
+ }
+ return $dom;
+ }
+ 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() ?? '', '|');
+ if (\false !== $pos) {
+ $objectXML->setAttribute('shortcut', '-' . \substr($option->getShortcut(), 0, $pos));
+ $objectXML->setAttribute('shortcuts', '-' . \str_replace('|', '|-', $option->getShortcut()));
+ } else {
+ $objectXML->setAttribute('shortcut', $option->getShortcut() ? '-' . $option->getShortcut() : '');
+ }
+ $objectXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0);
+ $objectXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0);
+ $objectXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0);
+ $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
+ $descriptionXML->appendChild($dom->createTextNode($option->getDescription()));
+ if ($option->acceptValue()) {
+ $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)) {
+ foreach ($defaults as $default) {
+ $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
+ $defaultXML->appendChild($dom->createTextNode($default));
+ }
+ }
+ }
+ 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;
+ }
+}
diff --git a/vendor/symfony/console/Event/ConsoleCommandEvent.php b/vendor/symfony/console/Event/ConsoleCommandEvent.php
new file mode 100644
index 00000000..af8e4ddb
--- /dev/null
+++ b/vendor/symfony/console/Event/ConsoleCommandEvent.php
@@ -0,0 +1,47 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Event;
+
+/**
+ * Allows to do things before the command is executed, like skipping the command or changing the input.
+ *
+ * @author Fabien Potencier
+ */
+final class ConsoleCommandEvent extends ConsoleEvent
+{
+ /**
+ * The return code for skipped commands, this will also be passed into the terminate event.
+ */
+ public const RETURN_CODE_DISABLED = 113;
+ /**
+ * Indicates if the command should be run or skipped.
+ * @var bool
+ */
+ private $commandShouldRun = \true;
+ /**
+ * Disables the command, so it won't be run.
+ */
+ public function disableCommand() : bool
+ {
+ return $this->commandShouldRun = \false;
+ }
+ public function enableCommand() : bool
+ {
+ return $this->commandShouldRun = \true;
+ }
+ /**
+ * Returns true if the command is runnable, false otherwise.
+ */
+ public function commandShouldRun() : bool
+ {
+ return $this->commandShouldRun;
+ }
+}
diff --git a/vendor/symfony/console/Event/ConsoleErrorEvent.php b/vendor/symfony/console/Event/ConsoleErrorEvent.php
new file mode 100644
index 00000000..207ecf61
--- /dev/null
+++ b/vendor/symfony/console/Event/ConsoleErrorEvent.php
@@ -0,0 +1,54 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Event;
+
+use ClassLeak202307\Symfony\Component\Console\Command\Command;
+use ClassLeak202307\Symfony\Component\Console\Input\InputInterface;
+use ClassLeak202307\Symfony\Component\Console\Output\OutputInterface;
+/**
+ * Allows to handle throwables thrown while running a command.
+ *
+ * @author Wouter de Jong
+ */
+final class ConsoleErrorEvent extends ConsoleEvent
+{
+ /**
+ * @var \Throwable
+ */
+ private $error;
+ /**
+ * @var int
+ */
+ private $exitCode;
+ public function __construct(InputInterface $input, OutputInterface $output, \Throwable $error, Command $command = null)
+ {
+ parent::__construct($command, $input, $output);
+ $this->error = $error;
+ }
+ public function getError() : \Throwable
+ {
+ 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->setValue($this->error, $this->exitCode);
+ }
+ public function getExitCode() : int
+ {
+ return $this->exitCode ?? (\is_int($this->error->getCode()) && 0 !== $this->error->getCode() ? $this->error->getCode() : 1);
+ }
+}
diff --git a/vendor/symfony/console/Event/ConsoleEvent.php b/vendor/symfony/console/Event/ConsoleEvent.php
new file mode 100644
index 00000000..a2790faa
--- /dev/null
+++ b/vendor/symfony/console/Event/ConsoleEvent.php
@@ -0,0 +1,60 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Event;
+
+use ClassLeak202307\Symfony\Component\Console\Command\Command;
+use ClassLeak202307\Symfony\Component\Console\Input\InputInterface;
+use ClassLeak202307\Symfony\Component\Console\Output\OutputInterface;
+use ClassLeak202307\Symfony\Contracts\EventDispatcher\Event;
+/**
+ * Allows to inspect input and output of a command.
+ *
+ * @author Francesco Levorato
+ */
+class ConsoleEvent extends Event
+{
+ protected $command;
+ /**
+ * @var \Symfony\Component\Console\Input\InputInterface
+ */
+ private $input;
+ /**
+ * @var \Symfony\Component\Console\Output\OutputInterface
+ */
+ private $output;
+ public function __construct(?Command $command, InputInterface $input, OutputInterface $output)
+ {
+ $this->command = $command;
+ $this->input = $input;
+ $this->output = $output;
+ }
+ /**
+ * Gets the command that is executed.
+ */
+ public function getCommand() : ?Command
+ {
+ return $this->command;
+ }
+ /**
+ * Gets the input instance.
+ */
+ public function getInput() : InputInterface
+ {
+ return $this->input;
+ }
+ /**
+ * Gets the output instance.
+ */
+ public function getOutput() : OutputInterface
+ {
+ return $this->output;
+ }
+}
diff --git a/vendor/symfony/console/Event/ConsoleSignalEvent.php b/vendor/symfony/console/Event/ConsoleSignalEvent.php
new file mode 100644
index 00000000..cfa2f834
--- /dev/null
+++ b/vendor/symfony/console/Event/ConsoleSignalEvent.php
@@ -0,0 +1,60 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Event;
+
+use ClassLeak202307\Symfony\Component\Console\Command\Command;
+use ClassLeak202307\Symfony\Component\Console\Input\InputInterface;
+use ClassLeak202307\Symfony\Component\Console\Output\OutputInterface;
+/**
+ * @author marie
+ */
+final class ConsoleSignalEvent extends ConsoleEvent
+{
+ /**
+ * @var int
+ */
+ private $handlingSignal;
+ /**
+ * @var int|false
+ */
+ private $exitCode;
+ /**
+ * @param int|false $exitCode
+ */
+ public function __construct(Command $command, InputInterface $input, OutputInterface $output, int $handlingSignal, $exitCode = 0)
+ {
+ parent::__construct($command, $input, $output);
+ $this->handlingSignal = $handlingSignal;
+ $this->exitCode = $exitCode;
+ }
+ public function getHandlingSignal() : int
+ {
+ return $this->handlingSignal;
+ }
+ public function setExitCode(int $exitCode) : void
+ {
+ if ($exitCode < 0 || $exitCode > 255) {
+ throw new \InvalidArgumentException('Exit code must be between 0 and 255.');
+ }
+ $this->exitCode = $exitCode;
+ }
+ public function abortExit() : void
+ {
+ $this->exitCode = \false;
+ }
+ /**
+ * @return int|false
+ */
+ public function getExitCode()
+ {
+ return $this->exitCode;
+ }
+}
diff --git a/vendor/symfony/console/Event/ConsoleTerminateEvent.php b/vendor/symfony/console/Event/ConsoleTerminateEvent.php
new file mode 100644
index 00000000..84edca59
--- /dev/null
+++ b/vendor/symfony/console/Event/ConsoleTerminateEvent.php
@@ -0,0 +1,40 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Event;
+
+use ClassLeak202307\Symfony\Component\Console\Command\Command;
+use ClassLeak202307\Symfony\Component\Console\Input\InputInterface;
+use ClassLeak202307\Symfony\Component\Console\Output\OutputInterface;
+/**
+ * Allows to manipulate the exit code of a command after its execution.
+ *
+ * @author Francesco Levorato
+ */
+final class ConsoleTerminateEvent extends ConsoleEvent
+{
+ /**
+ * @var int
+ */
+ private $exitCode;
+ public function __construct(Command $command, InputInterface $input, OutputInterface $output, int $exitCode)
+ {
+ parent::__construct($command, $input, $output);
+ $this->setExitCode($exitCode);
+ }
+ public function setExitCode(int $exitCode) : void
+ {
+ $this->exitCode = $exitCode;
+ }
+ public function getExitCode() : int
+ {
+ return $this->exitCode;
+ }
+}
diff --git a/vendor/symfony/console/EventListener/ErrorListener.php b/vendor/symfony/console/EventListener/ErrorListener.php
new file mode 100644
index 00000000..38153c64
--- /dev/null
+++ b/vendor/symfony/console/EventListener/ErrorListener.php
@@ -0,0 +1,82 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\EventListener;
+
+use ClassLeak202307\Psr\Log\LoggerInterface;
+use ClassLeak202307\Symfony\Component\Console\ConsoleEvents;
+use ClassLeak202307\Symfony\Component\Console\Event\ConsoleErrorEvent;
+use ClassLeak202307\Symfony\Component\Console\Event\ConsoleEvent;
+use ClassLeak202307\Symfony\Component\Console\Event\ConsoleTerminateEvent;
+use ClassLeak202307\Symfony\Component\EventDispatcher\EventSubscriberInterface;
+/**
+ * @author James Halsall
+ * @author Robin Chalas
+ */
+class ErrorListener implements EventSubscriberInterface
+{
+ /**
+ * @var \Psr\Log\LoggerInterface|null
+ */
+ private $logger;
+ public function __construct(LoggerInterface $logger = null)
+ {
+ $this->logger = $logger;
+ }
+ /**
+ * @return void
+ */
+ public function onConsoleError(ConsoleErrorEvent $event)
+ {
+ if (null === $this->logger) {
+ return;
+ }
+ $error = $event->getError();
+ if (!($inputString = $this->getInputString($event))) {
+ $this->logger->critical('An error occurred while using the console. Message: "{message}"', ['exception' => $error, 'message' => $error->getMessage()]);
+ return;
+ }
+ $this->logger->critical('Error thrown while running command "{command}". Message: "{message}"', ['exception' => $error, 'command' => $inputString, 'message' => $error->getMessage()]);
+ }
+ /**
+ * @return void
+ */
+ public function onConsoleTerminate(ConsoleTerminateEvent $event)
+ {
+ if (null === $this->logger) {
+ return;
+ }
+ $exitCode = $event->getExitCode();
+ if (0 === $exitCode) {
+ return;
+ }
+ if (!($inputString = $this->getInputString($event))) {
+ $this->logger->debug('The console exited with code "{code}"', ['code' => $exitCode]);
+ return;
+ }
+ $this->logger->debug('Command "{command}" exited with code "{code}"', ['command' => $inputString, 'code' => $exitCode]);
+ }
+ public static function getSubscribedEvents() : array
+ {
+ return [ConsoleEvents::ERROR => ['onConsoleError', -128], ConsoleEvents::TERMINATE => ['onConsoleTerminate', -128]];
+ }
+ private static function getInputString(ConsoleEvent $event) : ?string
+ {
+ $commandName = ($getCommand = $event->getCommand()) ? $getCommand->getName() : null;
+ $input = $event->getInput();
+ if ($input instanceof \Stringable) {
+ if ($commandName) {
+ return \str_replace(["'{$commandName}'", "\"{$commandName}\""], $commandName, (string) $input);
+ }
+ return (string) $input;
+ }
+ return $commandName;
+ }
+}
diff --git a/vendor/symfony/console/Exception/CommandNotFoundException.php b/vendor/symfony/console/Exception/CommandNotFoundException.php
new file mode 100644
index 00000000..b2db46db
--- /dev/null
+++ b/vendor/symfony/console/Exception/CommandNotFoundException.php
@@ -0,0 +1,42 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Exception;
+
+/**
+ * Represents an incorrect command name typed in the console.
+ *
+ * @author Jérôme Tamarelle
+ */
+class CommandNotFoundException extends \InvalidArgumentException implements ExceptionInterface
+{
+ /**
+ * @var mixed[]
+ */
+ private $alternatives;
+ /**
+ * @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(string $message, array $alternatives = [], int $code = 0, \Throwable $previous = null)
+ {
+ parent::__construct($message, $code, $previous);
+ $this->alternatives = $alternatives;
+ }
+ /**
+ * @return string[]
+ */
+ public function getAlternatives() : array
+ {
+ return $this->alternatives;
+ }
+}
diff --git a/vendor/symfony/console/Exception/ExceptionInterface.php b/vendor/symfony/console/Exception/ExceptionInterface.php
new file mode 100644
index 00000000..c66ae338
--- /dev/null
+++ b/vendor/symfony/console/Exception/ExceptionInterface.php
@@ -0,0 +1,20 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Exception;
+
+/**
+ * ExceptionInterface.
+ *
+ * @author Jérôme Tamarelle
+ */
+interface ExceptionInterface extends \Throwable
+{
+}
diff --git a/vendor/symfony/console/Exception/InvalidArgumentException.php b/vendor/symfony/console/Exception/InvalidArgumentException.php
new file mode 100644
index 00000000..8d419004
--- /dev/null
+++ b/vendor/symfony/console/Exception/InvalidArgumentException.php
@@ -0,0 +1,18 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Exception;
+
+/**
+ * @author Jérôme Tamarelle
+ */
+class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
+{
+}
diff --git a/vendor/symfony/console/Exception/InvalidOptionException.php b/vendor/symfony/console/Exception/InvalidOptionException.php
new file mode 100644
index 00000000..6644d06d
--- /dev/null
+++ b/vendor/symfony/console/Exception/InvalidOptionException.php
@@ -0,0 +1,20 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Exception;
+
+/**
+ * Represents an incorrect option name or value typed in the console.
+ *
+ * @author Jérôme Tamarelle
+ */
+class InvalidOptionException extends \InvalidArgumentException implements ExceptionInterface
+{
+}
diff --git a/vendor/symfony/console/Exception/LogicException.php b/vendor/symfony/console/Exception/LogicException.php
new file mode 100644
index 00000000..c317839e
--- /dev/null
+++ b/vendor/symfony/console/Exception/LogicException.php
@@ -0,0 +1,18 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Exception;
+
+/**
+ * @author Jérôme Tamarelle
+ */
+class LogicException extends \LogicException implements ExceptionInterface
+{
+}
diff --git a/vendor/symfony/console/Exception/MissingInputException.php b/vendor/symfony/console/Exception/MissingInputException.php
new file mode 100644
index 00000000..9c4e4d3f
--- /dev/null
+++ b/vendor/symfony/console/Exception/MissingInputException.php
@@ -0,0 +1,20 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Exception;
+
+/**
+ * Represents failure to read input from stdin.
+ *
+ * @author Gabriel Ostrolucký
+ */
+class MissingInputException extends RuntimeException implements ExceptionInterface
+{
+}
diff --git a/vendor/symfony/console/Exception/NamespaceNotFoundException.php b/vendor/symfony/console/Exception/NamespaceNotFoundException.php
new file mode 100644
index 00000000..bb1bc101
--- /dev/null
+++ b/vendor/symfony/console/Exception/NamespaceNotFoundException.php
@@ -0,0 +1,20 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Exception;
+
+/**
+ * Represents an incorrect namespace typed in the console.
+ *
+ * @author Pierre du Plessis
+ */
+class NamespaceNotFoundException extends CommandNotFoundException
+{
+}
diff --git a/vendor/symfony/console/Exception/RuntimeException.php b/vendor/symfony/console/Exception/RuntimeException.php
new file mode 100644
index 00000000..c1b7f79e
--- /dev/null
+++ b/vendor/symfony/console/Exception/RuntimeException.php
@@ -0,0 +1,18 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Exception;
+
+/**
+ * @author Jérôme Tamarelle
+ */
+class RuntimeException extends \RuntimeException implements ExceptionInterface
+{
+}
diff --git a/vendor/symfony/console/Formatter/NullOutputFormatter.php b/vendor/symfony/console/Formatter/NullOutputFormatter.php
new file mode 100644
index 00000000..953b175c
--- /dev/null
+++ b/vendor/symfony/console/Formatter/NullOutputFormatter.php
@@ -0,0 +1,47 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Formatter;
+
+/**
+ * @author Tien Xuan Vo
+ */
+final class NullOutputFormatter implements OutputFormatterInterface
+{
+ /**
+ * @var \Symfony\Component\Console\Formatter\NullOutputFormatterStyle
+ */
+ private $style;
+ public function format(?string $message) : ?string
+ {
+ return null;
+ }
+ public function getStyle(string $name) : OutputFormatterStyleInterface
+ {
+ // to comply with the interface we must return a OutputFormatterStyleInterface
+ return $this->style = $this->style ?? new NullOutputFormatterStyle();
+ }
+ public function hasStyle(string $name) : bool
+ {
+ return \false;
+ }
+ public function isDecorated() : bool
+ {
+ return \false;
+ }
+ public function setDecorated(bool $decorated) : void
+ {
+ // do nothing
+ }
+ public function setStyle(string $name, OutputFormatterStyleInterface $style) : void
+ {
+ // do nothing
+ }
+}
diff --git a/vendor/symfony/console/Formatter/NullOutputFormatterStyle.php b/vendor/symfony/console/Formatter/NullOutputFormatterStyle.php
new file mode 100644
index 00000000..1ef7057e
--- /dev/null
+++ b/vendor/symfony/console/Formatter/NullOutputFormatterStyle.php
@@ -0,0 +1,48 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Formatter;
+
+/**
+ * @author Tien Xuan Vo
+ */
+final class NullOutputFormatterStyle implements OutputFormatterStyleInterface
+{
+ public function apply(string $text) : string
+ {
+ return $text;
+ }
+ public function setBackground(string $color = null) : void
+ {
+ if (1 > \func_num_args()) {
+ trigger_deprecation('symfony/console', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
+ }
+ // do nothing
+ }
+ public function setForeground(string $color = null) : void
+ {
+ if (1 > \func_num_args()) {
+ trigger_deprecation('symfony/console', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
+ }
+ // do nothing
+ }
+ public function setOption(string $option) : void
+ {
+ // do nothing
+ }
+ public function setOptions(array $options) : void
+ {
+ // do nothing
+ }
+ public function unsetOption(string $option) : void
+ {
+ // do nothing
+ }
+}
diff --git a/vendor/symfony/console/Formatter/OutputFormatter.php b/vendor/symfony/console/Formatter/OutputFormatter.php
new file mode 100644
index 00000000..072dd618
--- /dev/null
+++ b/vendor/symfony/console/Formatter/OutputFormatter.php
@@ -0,0 +1,235 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Formatter;
+
+use ClassLeak202307\Symfony\Component\Console\Exception\InvalidArgumentException;
+/**
+ * Formatter class for console output.
+ *
+ * @author Konstantin Kudryashov
+ * @author Roland Franssen
+ */
+class OutputFormatter implements WrappableOutputFormatterInterface
+{
+ /**
+ * @var bool
+ */
+ private $decorated;
+ /**
+ * @var mixed[]
+ */
+ private $styles = [];
+ /**
+ * @var \Symfony\Component\Console\Formatter\OutputFormatterStyleStack
+ */
+ private $styleStack;
+ public function __clone()
+ {
+ $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);
+ }
+ /**
+ * Escapes trailing "\" in given text.
+ *
+ * @internal
+ */
+ public static function escapeTrailingBackslash(string $text) : string
+ {
+ if (\substr_compare($text, '\\', -\strlen('\\')) === 0) {
+ $len = \strlen($text);
+ $text = \rtrim($text, '\\');
+ $text = \str_replace("\x00", '', $text);
+ $text .= \str_repeat("\x00", $len - \strlen($text));
+ }
+ return $text;
+ }
+ /**
+ * Initializes console output formatter.
+ *
+ * @param OutputFormatterStyleInterface[] $styles Array of "name => FormatterStyle" instances
+ */
+ public function __construct(bool $decorated = \false, array $styles = [])
+ {
+ $this->decorated = $decorated;
+ $this->setStyle('error', new OutputFormatterStyle('white', 'red'));
+ $this->setStyle('info', new OutputFormatterStyle('green'));
+ $this->setStyle('comment', new OutputFormatterStyle('yellow'));
+ $this->setStyle('question', new OutputFormatterStyle('black', 'cyan'));
+ foreach ($styles as $name => $style) {
+ $this->setStyle($name, $style);
+ }
+ $this->styleStack = new OutputFormatterStyleStack();
+ }
+ /**
+ * @return void
+ */
+ public function setDecorated(bool $decorated)
+ {
+ $this->decorated = $decorated;
+ }
+ public function isDecorated() : bool
+ {
+ return $this->decorated;
+ }
+ /**
+ * @return void
+ */
+ public function setStyle(string $name, OutputFormatterStyleInterface $style)
+ {
+ $this->styles[\strtolower($name)] = $style;
+ }
+ public function hasStyle(string $name) : bool
+ {
+ return isset($this->styles[\strtolower($name)]);
+ }
+ public function getStyle(string $name) : OutputFormatterStyleInterface
+ {
+ if (!$this->hasStyle($name)) {
+ throw new InvalidArgumentException(\sprintf('Undefined style: "%s".', $name));
+ }
+ return $this->styles[\strtolower($name)];
+ }
+ public function format(?string $message) : ?string
+ {
+ return $this->formatAndWrap($message, 0);
+ }
+ /**
+ * @return string
+ */
+ public function formatAndWrap(?string $message, int $width)
+ {
+ if (null === $message) {
+ return '';
+ }
+ $offset = 0;
+ $output = '';
+ $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];
+ if (0 != $pos && '\\' == $message[$pos - 1]) {
+ continue;
+ }
+ // add the text up to the next tag
+ $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 = $matches[3][$i][0] ?? '';
+ }
+ if (!$open && !$tag) {
+ // >
+ $this->styleStack->pop();
+ } elseif (null === ($style = $this->createStyleFromString($tag))) {
+ $output .= $this->applyCurrentStyle($text, $output, $width, $currentLineLength);
+ } elseif ($open) {
+ $this->styleStack->push($style);
+ } else {
+ $this->styleStack->pop($style);
+ }
+ }
+ $output .= $this->applyCurrentStyle(\substr($message, $offset), $output, $width, $currentLineLength);
+ return \strtr($output, ["\x00" => '\\', '\\<' => '<', '\\>' => '>']);
+ }
+ public function getStyleStack() : OutputFormatterStyleStack
+ {
+ return $this->styleStack;
+ }
+ /**
+ * Tries to create new style instance from 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 null;
+ }
+ $style = new OutputFormatterStyle();
+ foreach ($matches as $match) {
+ \array_shift($match);
+ $match[0] = \strtolower($match[0]);
+ if ('fg' == $match[0]) {
+ $style->setForeground(\strtolower($match[1]));
+ } elseif ('bg' == $match[0]) {
+ $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('([^,;]+)', \strtolower($match[1]), $options);
+ $options = \array_shift($options);
+ foreach ($options as $option) {
+ $style->setOption($option);
+ }
+ } else {
+ return null;
+ }
+ }
+ return $style;
+ }
+ /**
+ * Applies current style from stack to text, if must be applied.
+ */
+ private function applyCurrentStyle(string $text, string $current, int $width, int &$currentLineLength) : string
+ {
+ 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 && \substr_compare($current, "\n", -\strlen("\n")) !== 0) {
+ $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);
+ }
+}
diff --git a/vendor/symfony/console/Formatter/OutputFormatterInterface.php b/vendor/symfony/console/Formatter/OutputFormatterInterface.php
new file mode 100644
index 00000000..7fa5810a
--- /dev/null
+++ b/vendor/symfony/console/Formatter/OutputFormatterInterface.php
@@ -0,0 +1,50 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Formatter;
+
+/**
+ * Formatter interface for console output.
+ *
+ * @author Konstantin Kudryashov
+ */
+interface OutputFormatterInterface
+{
+ /**
+ * Sets the decorated flag.
+ *
+ * @return void
+ */
+ public function setDecorated(bool $decorated);
+ /**
+ * Whether the output will decorate messages.
+ */
+ public function isDecorated() : bool;
+ /**
+ * Sets a new style.
+ *
+ * @return void
+ */
+ public function setStyle(string $name, OutputFormatterStyleInterface $style);
+ /**
+ * Checks if output formatter has style with specified name.
+ */
+ public function hasStyle(string $name) : bool;
+ /**
+ * Gets style options from style with specified name.
+ *
+ * @throws \InvalidArgumentException When style isn't defined
+ */
+ public function getStyle(string $name) : OutputFormatterStyleInterface;
+ /**
+ * Formats a message according to the given styles.
+ */
+ public function format(?string $message) : ?string;
+}
diff --git a/vendor/symfony/console/Formatter/OutputFormatterStyle.php b/vendor/symfony/console/Formatter/OutputFormatterStyle.php
new file mode 100644
index 00000000..15637f8c
--- /dev/null
+++ b/vendor/symfony/console/Formatter/OutputFormatterStyle.php
@@ -0,0 +1,113 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Formatter;
+
+use ClassLeak202307\Symfony\Component\Console\Color;
+/**
+ * Formatter style class for defining styles.
+ *
+ * @author Konstantin Kudryashov
+ */
+class OutputFormatterStyle implements OutputFormatterStyleInterface
+{
+ /**
+ * @var \Symfony\Component\Console\Color
+ */
+ private $color;
+ /**
+ * @var string
+ */
+ private $foreground;
+ /**
+ * @var string
+ */
+ private $background;
+ /**
+ * @var mixed[]
+ */
+ private $options;
+ /**
+ * @var string|null
+ */
+ private $href;
+ /**
+ * @var bool
+ */
+ private $handlesHrefGracefully;
+ /**
+ * Initializes output formatter style.
+ *
+ * @param string|null $foreground The style foreground color name
+ * @param string|null $background The style background color name
+ */
+ public function __construct(string $foreground = null, string $background = null, array $options = [])
+ {
+ $this->color = new Color($this->foreground = $foreground ?: '', $this->background = $background ?: '', $this->options = $options);
+ }
+ /**
+ * @return void
+ */
+ public function setForeground(string $color = null)
+ {
+ if (1 > \func_num_args()) {
+ trigger_deprecation('symfony/console', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
+ }
+ $this->color = new Color($this->foreground = $color ?: '', $this->background, $this->options);
+ }
+ /**
+ * @return void
+ */
+ public function setBackground(string $color = null)
+ {
+ if (1 > \func_num_args()) {
+ trigger_deprecation('symfony/console', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
+ }
+ $this->color = new Color($this->foreground, $this->background = $color ?: '', $this->options);
+ }
+ public function setHref(string $url) : void
+ {
+ $this->href = $url;
+ }
+ /**
+ * @return void
+ */
+ public function setOption(string $option)
+ {
+ $this->options[] = $option;
+ $this->color = new Color($this->foreground, $this->background, $this->options);
+ }
+ /**
+ * @return void
+ */
+ public function unsetOption(string $option)
+ {
+ $pos = \array_search($option, $this->options);
+ if (\false !== $pos) {
+ unset($this->options[$pos]);
+ }
+ $this->color = new Color($this->foreground, $this->background, $this->options);
+ }
+ /**
+ * @return void
+ */
+ public function setOptions(array $options)
+ {
+ $this->color = new Color($this->foreground, $this->background, $this->options = $options);
+ }
+ public function apply(string $text) : string
+ {
+ $this->handlesHrefGracefully = $this->handlesHrefGracefully ?? 'JetBrains-JediTerm' !== \getenv('TERMINAL_EMULATOR') && (!\getenv('KONSOLE_VERSION') || (int) \getenv('KONSOLE_VERSION') > 201100) && !isset($_SERVER['IDEA_INITIAL_DIRECTORY']);
+ if (null !== $this->href && $this->handlesHrefGracefully) {
+ $text = "\x1b]8;;{$this->href}\x1b\\{$text}\x1b]8;;\x1b\\";
+ }
+ return $this->color->apply($text);
+ }
+}
diff --git a/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php b/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php
new file mode 100644
index 00000000..360b0395
--- /dev/null
+++ b/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php
@@ -0,0 +1,54 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Formatter;
+
+/**
+ * Formatter style interface for defining styles.
+ *
+ * @author Konstantin Kudryashov
+ */
+interface OutputFormatterStyleInterface
+{
+ /**
+ * Sets style foreground color.
+ *
+ * @return void
+ */
+ public function setForeground(?string $color);
+ /**
+ * Sets style background color.
+ *
+ * @return void
+ */
+ public function setBackground(?string $color);
+ /**
+ * Sets some specific style option.
+ *
+ * @return void
+ */
+ public function setOption(string $option);
+ /**
+ * Unsets some specific style option.
+ *
+ * @return void
+ */
+ public function unsetOption(string $option);
+ /**
+ * Sets multiple style options at once.
+ *
+ * @return void
+ */
+ public function setOptions(array $options);
+ /**
+ * Applies the style to a given text.
+ */
+ public function apply(string $text) : string;
+}
diff --git a/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php b/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php
new file mode 100644
index 00000000..aa6c82aa
--- /dev/null
+++ b/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php
@@ -0,0 +1,94 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Formatter;
+
+use ClassLeak202307\Symfony\Component\Console\Exception\InvalidArgumentException;
+use ClassLeak202307\Symfony\Contracts\Service\ResetInterface;
+/**
+ * @author Jean-François Simon
+ */
+class OutputFormatterStyleStack implements ResetInterface
+{
+ /**
+ * @var OutputFormatterStyleInterface[]
+ */
+ private $styles = [];
+ /**
+ * @var \Symfony\Component\Console\Formatter\OutputFormatterStyleInterface
+ */
+ private $emptyStyle;
+ public function __construct(OutputFormatterStyleInterface $emptyStyle = null)
+ {
+ $this->emptyStyle = $emptyStyle ?? new OutputFormatterStyle();
+ $this->reset();
+ }
+ /**
+ * Resets stack (ie. empty internal arrays).
+ *
+ * @return void
+ */
+ public function reset()
+ {
+ $this->styles = [];
+ }
+ /**
+ * Pushes a style in the stack.
+ *
+ * @return void
+ */
+ public function push(OutputFormatterStyleInterface $style)
+ {
+ $this->styles[] = $style;
+ }
+ /**
+ * Pops a style from the stack.
+ *
+ * @throws InvalidArgumentException When style tags incorrectly nested
+ */
+ public function pop(OutputFormatterStyleInterface $style = null) : OutputFormatterStyleInterface
+ {
+ if (!$this->styles) {
+ return $this->emptyStyle;
+ }
+ if (null === $style) {
+ return \array_pop($this->styles);
+ }
+ foreach (\array_reverse($this->styles, \true) as $index => $stackedStyle) {
+ if ($style->apply('') === $stackedStyle->apply('')) {
+ $this->styles = \array_slice($this->styles, 0, $index);
+ return $stackedStyle;
+ }
+ }
+ throw new InvalidArgumentException('Incorrectly nested style tag found.');
+ }
+ /**
+ * Computes current style with stacks top codes.
+ */
+ public function getCurrent() : OutputFormatterStyleInterface
+ {
+ if (!$this->styles) {
+ return $this->emptyStyle;
+ }
+ return $this->styles[\count($this->styles) - 1];
+ }
+ /**
+ * @return $this
+ */
+ public function setEmptyStyle(OutputFormatterStyleInterface $emptyStyle)
+ {
+ $this->emptyStyle = $emptyStyle;
+ return $this;
+ }
+ public function getEmptyStyle() : OutputFormatterStyleInterface
+ {
+ return $this->emptyStyle;
+ }
+}
diff --git a/vendor/symfony/console/Formatter/WrappableOutputFormatterInterface.php b/vendor/symfony/console/Formatter/WrappableOutputFormatterInterface.php
new file mode 100644
index 00000000..62b84112
--- /dev/null
+++ b/vendor/symfony/console/Formatter/WrappableOutputFormatterInterface.php
@@ -0,0 +1,26 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Formatter;
+
+/**
+ * Formatter interface for console output that supports word wrapping.
+ *
+ * @author Roland Franssen
+ */
+interface WrappableOutputFormatterInterface extends OutputFormatterInterface
+{
+ /**
+ * Formats a message according to the given styles, wrapping at `$width` (0 means no wrapping).
+ *
+ * @return string
+ */
+ public function formatAndWrap(?string $message, int $width);
+}
diff --git a/vendor/symfony/console/Helper/DebugFormatterHelper.php b/vendor/symfony/console/Helper/DebugFormatterHelper.php
new file mode 100644
index 00000000..59408e6b
--- /dev/null
+++ b/vendor/symfony/console/Helper/DebugFormatterHelper.php
@@ -0,0 +1,89 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Helper;
+
+/**
+ * Helps outputting debug information when running an external program from a command.
+ *
+ * An external program can be a Process, an HTTP request, or anything else.
+ *
+ * @author Fabien Potencier
+ */
+class DebugFormatterHelper extends Helper
+{
+ private const COLORS = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'default'];
+ /**
+ * @var mixed[]
+ */
+ private $started = [];
+ /**
+ * @var int
+ */
+ private $count = -1;
+ /**
+ * Starts a debug formatting session.
+ */
+ public function start(string $id, string $message, string $prefix = 'RUN') : string
+ {
+ $this->started[$id] = ['border' => ++$this->count % \count(self::COLORS)];
+ return \sprintf("%s %s > %s>\n", $this->getBorder($id), $prefix, $message);
+ }
+ /**
+ * Adds progress to a formatting session.
+ */
+ public function progress(string $id, string $buffer, bool $error = \false, string $prefix = 'OUT', string $errorPrefix = 'ERR') : string
+ {
+ $message = '';
+ if ($error) {
+ if (isset($this->started[$id]['out'])) {
+ $message .= "\n";
+ unset($this->started[$id]['out']);
+ }
+ if (!isset($this->started[$id]['err'])) {
+ $message .= \sprintf('%s %s > ', $this->getBorder($id), $errorPrefix);
+ $this->started[$id]['err'] = \true;
+ }
+ $message .= \str_replace("\n", \sprintf("\n%s %s > ", $this->getBorder($id), $errorPrefix), $buffer);
+ } else {
+ if (isset($this->started[$id]['err'])) {
+ $message .= "\n";
+ unset($this->started[$id]['err']);
+ }
+ if (!isset($this->started[$id]['out'])) {
+ $message .= \sprintf('%s %s > ', $this->getBorder($id), $prefix);
+ $this->started[$id]['out'] = \true;
+ }
+ $message .= \str_replace("\n", \sprintf("\n%s %s > ", $this->getBorder($id), $prefix), $buffer);
+ }
+ return $message;
+ }
+ /**
+ * Stops a formatting session.
+ */
+ 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" : '';
+ if ($successful) {
+ return \sprintf("%s%s %s > %s>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);
+ }
+ $message = \sprintf("%s%s %s > %s>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);
+ unset($this->started[$id]['out'], $this->started[$id]['err']);
+ return $message;
+ }
+ private function getBorder(string $id) : string
+ {
+ return \sprintf(' >', self::COLORS[$this->started[$id]['border']]);
+ }
+ public function getName() : string
+ {
+ return 'debug_formatter';
+ }
+}
diff --git a/vendor/symfony/console/Helper/DescriptorHelper.php b/vendor/symfony/console/Helper/DescriptorHelper.php
new file mode 100644
index 00000000..778b934d
--- /dev/null
+++ b/vendor/symfony/console/Helper/DescriptorHelper.php
@@ -0,0 +1,74 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Helper;
+
+use ClassLeak202307\Symfony\Component\Console\Descriptor\DescriptorInterface;
+use ClassLeak202307\Symfony\Component\Console\Descriptor\JsonDescriptor;
+use ClassLeak202307\Symfony\Component\Console\Descriptor\MarkdownDescriptor;
+use ClassLeak202307\Symfony\Component\Console\Descriptor\ReStructuredTextDescriptor;
+use ClassLeak202307\Symfony\Component\Console\Descriptor\TextDescriptor;
+use ClassLeak202307\Symfony\Component\Console\Descriptor\XmlDescriptor;
+use ClassLeak202307\Symfony\Component\Console\Exception\InvalidArgumentException;
+use ClassLeak202307\Symfony\Component\Console\Output\OutputInterface;
+/**
+ * This class adds helper method to describe objects in various formats.
+ *
+ * @author Jean-François Simon
+ */
+class DescriptorHelper extends Helper
+{
+ /**
+ * @var DescriptorInterface[]
+ */
+ private $descriptors = [];
+ public function __construct()
+ {
+ $this->register('txt', new TextDescriptor())->register('xml', new XmlDescriptor())->register('json', new JsonDescriptor())->register('md', new MarkdownDescriptor())->register('rst', new ReStructuredTextDescriptor());
+ }
+ /**
+ * Describes an object if supported.
+ *
+ * Available options are:
+ * * format: string, the output format name
+ * * raw_text: boolean, sets output type as raw
+ *
+ * @return void
+ *
+ * @throws InvalidArgumentException when the given format is not supported
+ */
+ public function describe(OutputInterface $output, ?object $object, array $options = [])
+ {
+ $options = \array_merge(['raw_text' => \false, 'format' => 'txt'], $options);
+ if (!isset($this->descriptors[$options['format']])) {
+ throw new InvalidArgumentException(\sprintf('Unsupported format "%s".', $options['format']));
+ }
+ $descriptor = $this->descriptors[$options['format']];
+ $descriptor->describe($output, $object, $options);
+ }
+ /**
+ * Registers a descriptor.
+ *
+ * @return $this
+ */
+ public function register(string $format, DescriptorInterface $descriptor)
+ {
+ $this->descriptors[$format] = $descriptor;
+ return $this;
+ }
+ public function getName() : string
+ {
+ return 'descriptor';
+ }
+ public function getFormats() : array
+ {
+ return \array_keys($this->descriptors);
+ }
+}
diff --git a/vendor/symfony/console/Helper/Dumper.php b/vendor/symfony/console/Helper/Dumper.php
new file mode 100644
index 00000000..74a703cb
--- /dev/null
+++ b/vendor/symfony/console/Helper/Dumper.php
@@ -0,0 +1,73 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Helper;
+
+use ClassLeak202307\Symfony\Component\Console\Output\OutputInterface;
+use ClassLeak202307\Symfony\Component\VarDumper\Cloner\ClonerInterface;
+use ClassLeak202307\Symfony\Component\VarDumper\Cloner\VarCloner;
+use ClassLeak202307\Symfony\Component\VarDumper\Dumper\CliDumper;
+/**
+ * @author Roland Franssen
+ */
+final class Dumper
+{
+ /**
+ * @var \Symfony\Component\Console\Output\OutputInterface
+ */
+ private $output;
+ /**
+ * @var \Symfony\Component\VarDumper\Dumper\CliDumper|null
+ */
+ private $dumper;
+ /**
+ * @var \Symfony\Component\VarDumper\Cloner\ClonerInterface|null
+ */
+ private $cloner;
+ /**
+ * @var \Closure
+ */
+ private $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));
+ }
+ };
+ }
+ }
+ /**
+ * @param mixed $var
+ */
+ public function __invoke($var) : string
+ {
+ return ($this->handler)($var);
+ }
+}
diff --git a/vendor/symfony/console/Helper/FormatterHelper.php b/vendor/symfony/console/Helper/FormatterHelper.php
new file mode 100644
index 00000000..55d13d78
--- /dev/null
+++ b/vendor/symfony/console/Helper/FormatterHelper.php
@@ -0,0 +1,71 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Helper;
+
+use ClassLeak202307\Symfony\Component\Console\Formatter\OutputFormatter;
+/**
+ * The Formatter class provides helpers to format messages.
+ *
+ * @author Fabien Potencier
+ */
+class FormatterHelper extends Helper
+{
+ /**
+ * Formats a message within a section.
+ */
+ 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|mixed[] $messages
+ */
+ public function formatBlock($messages, string $style, bool $large = \false) : string
+ {
+ if (!\is_array($messages)) {
+ $messages = [$messages];
+ }
+ $len = 0;
+ $lines = [];
+ foreach ($messages as $message) {
+ $message = OutputFormatter::escape($message);
+ $lines[] = \sprintf($large ? ' %s ' : ' %s ', $message);
+ $len = \max(self::width($message) + ($large ? 4 : 2), $len);
+ }
+ $messages = $large ? [\str_repeat(' ', $len)] : [];
+ for ($i = 0; isset($lines[$i]); ++$i) {
+ $messages[] = $lines[$i] . \str_repeat(' ', $len - self::width($lines[$i]));
+ }
+ if ($large) {
+ $messages[] = \str_repeat(' ', $len);
+ }
+ for ($i = 0; isset($messages[$i]); ++$i) {
+ $messages[$i] = \sprintf('<%s>%s%s>', $style, $messages[$i], $style);
+ }
+ return \implode("\n", $messages);
+ }
+ /**
+ * Truncates a message to the given length.
+ */
+ public function truncate(string $message, int $length, string $suffix = '...') : string
+ {
+ $computedLength = $length - self::width($suffix);
+ if ($computedLength > self::width($message)) {
+ return $message;
+ }
+ return self::substr($message, 0, $length) . $suffix;
+ }
+ public function getName() : string
+ {
+ return 'formatter';
+ }
+}
diff --git a/vendor/symfony/console/Helper/Helper.php b/vendor/symfony/console/Helper/Helper.php
new file mode 100644
index 00000000..f4bbc0b1
--- /dev/null
+++ b/vendor/symfony/console/Helper/Helper.php
@@ -0,0 +1,128 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Helper;
+
+use ClassLeak202307\Symfony\Component\Console\Formatter\OutputFormatterInterface;
+use ClassLeak202307\Symfony\Component\String\UnicodeString;
+/**
+ * Helper is the base class for all helper classes.
+ *
+ * @author Fabien Potencier
+ */
+abstract class Helper implements HelperInterface
+{
+ protected $helperSet;
+ /**
+ * @return void
+ */
+ public function setHelperSet(HelperSet $helperSet = null)
+ {
+ if (1 > \func_num_args()) {
+ trigger_deprecation('symfony/console', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
+ }
+ $this->helperSet = $helperSet;
+ }
+ public function getHelperSet() : ?HelperSet
+ {
+ return $this->helperSet;
+ }
+ /**
+ * Returns the width of a string, using mb_strwidth if it is available.
+ * The width is how many characters positions the string will use.
+ */
+ public static function width(?string $string) : int
+ {
+ $string = $string ?? '';
+ if (\preg_match('//u', $string)) {
+ return (new UnicodeString($string))->width(\false);
+ }
+ if (\false === ($encoding = \mb_detect_encoding($string, null, \true))) {
+ return \strlen($string);
+ }
+ return \mb_strwidth($string, $encoding);
+ }
+ /**
+ * Returns the length of a string, using mb_strlen if it is available.
+ * The length is related to how many bytes the string will use.
+ */
+ public static function length(?string $string) : int
+ {
+ $string = $string ?? '';
+ if (\preg_match('//u', $string)) {
+ return (new UnicodeString($string))->length();
+ }
+ if (\false === ($encoding = \mb_detect_encoding($string, null, \true))) {
+ return \strlen($string);
+ }
+ return \mb_strlen($string, $encoding);
+ }
+ /**
+ * Returns the subset of a string, using mb_substr if it is available.
+ */
+ 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);
+ }
+ return \mb_substr($string, $from, $length, $encoding);
+ }
+ /**
+ * @return string
+ * @param int|float $secs
+ */
+ public static function formatTime($secs)
+ {
+ 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) {
+ if (2 == \count($format)) {
+ return $format[1];
+ }
+ return \floor($secs / $format[2]) . ' ' . $format[1];
+ }
+ }
+ }
+ }
+ /**
+ * @return string
+ */
+ public static function formatMemory(int $memory)
+ {
+ if ($memory >= 1024 * 1024 * 1024) {
+ return \sprintf('%.1f GiB', $memory / 1024 / 1024 / 1024);
+ }
+ if ($memory >= 1024 * 1024) {
+ return \sprintf('%.1f MiB', $memory / 1024 / 1024);
+ }
+ if ($memory >= 1024) {
+ return \sprintf('%d KiB', $memory / 1024);
+ }
+ return \sprintf('%d B', $memory);
+ }
+ /**
+ * @return string
+ */
+ public static function removeDecoration(OutputFormatterInterface $formatter, ?string $string)
+ {
+ $isDecorated = $formatter->isDecorated();
+ $formatter->setDecorated(\false);
+ // remove <...> formatting
+ $string = $formatter->format($string ?? '');
+ // remove already formatted characters
+ $string = \preg_replace("/\x1b\\[[^m]*m/", '', $string ?? '');
+ // remove terminal hyperlinks
+ $string = \preg_replace('/\\033]8;[^;]*;[^\\033]*\\033\\\\/', '', $string ?? '');
+ $formatter->setDecorated($isDecorated);
+ return $string;
+ }
+}
diff --git a/vendor/symfony/console/Helper/HelperInterface.php b/vendor/symfony/console/Helper/HelperInterface.php
new file mode 100644
index 00000000..dcf65e04
--- /dev/null
+++ b/vendor/symfony/console/Helper/HelperInterface.php
@@ -0,0 +1,36 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Helper;
+
+/**
+ * HelperInterface is the interface all helpers must implement.
+ *
+ * @author Fabien Potencier
+ */
+interface HelperInterface
+{
+ /**
+ * Sets the helper set associated with this helper.
+ *
+ * @return void
+ */
+ public function setHelperSet(?HelperSet $helperSet);
+ /**
+ * Gets the helper set associated with this helper.
+ */
+ public function getHelperSet() : ?HelperSet;
+ /**
+ * Returns the canonical name of this helper.
+ *
+ * @return string
+ */
+ public function getName();
+}
diff --git a/vendor/symfony/console/Helper/HelperSet.php b/vendor/symfony/console/Helper/HelperSet.php
new file mode 100644
index 00000000..b5066dd7
--- /dev/null
+++ b/vendor/symfony/console/Helper/HelperSet.php
@@ -0,0 +1,68 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Helper;
+
+use ClassLeak202307\Symfony\Component\Console\Exception\InvalidArgumentException;
+/**
+ * HelperSet represents a set of helpers to be used with a command.
+ *
+ * @author Fabien Potencier
+ *
+ * @implements \IteratorAggregate
+ */
+class HelperSet implements \IteratorAggregate
+{
+ /** @var array */
+ private $helpers = [];
+ /**
+ * @param HelperInterface[] $helpers
+ */
+ public function __construct(array $helpers = [])
+ {
+ foreach ($helpers as $alias => $helper) {
+ $this->set($helper, \is_int($alias) ? null : $alias);
+ }
+ }
+ /**
+ * @return void
+ */
+ public function set(HelperInterface $helper, string $alias = null)
+ {
+ $this->helpers[$helper->getName()] = $helper;
+ if (null !== $alias) {
+ $this->helpers[$alias] = $helper;
+ }
+ $helper->setHelperSet($this);
+ }
+ /**
+ * Returns true if the helper if defined.
+ */
+ public function has(string $name) : bool
+ {
+ return isset($this->helpers[$name]);
+ }
+ /**
+ * Gets a helper value.
+ *
+ * @throws InvalidArgumentException if the helper is not defined
+ */
+ public function get(string $name) : HelperInterface
+ {
+ if (!$this->has($name)) {
+ throw new InvalidArgumentException(\sprintf('The helper "%s" is not defined.', $name));
+ }
+ return $this->helpers[$name];
+ }
+ public function getIterator() : \Traversable
+ {
+ return new \ArrayIterator($this->helpers);
+ }
+}
diff --git a/vendor/symfony/console/Helper/InputAwareHelper.php b/vendor/symfony/console/Helper/InputAwareHelper.php
new file mode 100644
index 00000000..bf2a78a5
--- /dev/null
+++ b/vendor/symfony/console/Helper/InputAwareHelper.php
@@ -0,0 +1,30 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Helper;
+
+use ClassLeak202307\Symfony\Component\Console\Input\InputAwareInterface;
+use ClassLeak202307\Symfony\Component\Console\Input\InputInterface;
+/**
+ * An implementation of InputAwareInterface for Helpers.
+ *
+ * @author Wouter J
+ */
+abstract class InputAwareHelper extends Helper implements InputAwareInterface
+{
+ protected $input;
+ /**
+ * @return void
+ */
+ public function setInput(InputInterface $input)
+ {
+ $this->input = $input;
+ }
+}
diff --git a/vendor/symfony/console/Helper/OutputWrapper.php b/vendor/symfony/console/Helper/OutputWrapper.php
new file mode 100644
index 00000000..676fc381
--- /dev/null
+++ b/vendor/symfony/console/Helper/OutputWrapper.php
@@ -0,0 +1,75 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Helper;
+
+/**
+ * Simple output wrapper for "tagged outputs" instead of wordwrap(). This solution is based on a StackOverflow
+ * answer: https://stackoverflow.com/a/20434776/1476819 from user557597 (alias SLN).
+ *
+ * (?:
+ * # -- Words/Characters
+ * ( # (1 start)
+ * (?> # Atomic Group - Match words with valid breaks
+ * .{1,16} # 1-N characters
+ * # Followed by one of 4 prioritized, non-linebreak whitespace
+ * (?: # break types:
+ * (?<= [^\S\r\n] ) # 1. - Behind a non-linebreak whitespace
+ * [^\S\r\n]? # ( optionally accept an extra non-linebreak whitespace )
+ * | (?= \r? \n ) # 2. - Ahead a linebreak
+ * | $ # 3. - EOS
+ * | [^\S\r\n] # 4. - Accept an extra non-linebreak whitespace
+ * )
+ * ) # End atomic group
+ * |
+ * .{1,16} # No valid word breaks, just break on the N'th character
+ * ) # (1 end)
+ * (?: \r? \n )? # Optional linebreak after Words/Characters
+ * |
+ * # -- Or, Linebreak
+ * (?: \r? \n | $ ) # Stand alone linebreak or at EOS
+ * )
+ *
+ * @author Krisztián Ferenczi
+ *
+ * @see https://stackoverflow.com/a/20434776/1476819
+ */
+final class OutputWrapper
+{
+ /**
+ * @var bool
+ */
+ private $allowCutUrls = \false;
+ private const TAG_OPEN_REGEX_SEGMENT = '[a-z](?:[^\\\\<>]*+ | \\\\.)*';
+ private const TAG_CLOSE_REGEX_SEGMENT = '[a-z][^<>]*+';
+ private const URL_PATTERN = 'https?://\\S+';
+ public function __construct(bool $allowCutUrls = \false)
+ {
+ $this->allowCutUrls = $allowCutUrls;
+ }
+ public function wrap(string $text, int $width, string $break = "\n") : string
+ {
+ if (!$width) {
+ return $text;
+ }
+ $tagPattern = \sprintf('<(?:(?:%s)|/(?:%s)?)>', self::TAG_OPEN_REGEX_SEGMENT, self::TAG_CLOSE_REGEX_SEGMENT);
+ $limitPattern = "{1,{$width}}";
+ $patternBlocks = [$tagPattern];
+ if (!$this->allowCutUrls) {
+ $patternBlocks[] = self::URL_PATTERN;
+ }
+ $patternBlocks[] = '.';
+ $blocks = \implode('|', $patternBlocks);
+ $rowPattern = "(?:{$blocks}){$limitPattern}";
+ $pattern = \sprintf('#(?:((?>(%1$s)((?<=[^\\S\\r\\n])[^\\S\\r\\n]?|(?=\\r?\\n)|$|[^\\S\\r\\n]))|(%1$s))(?:\\r?\\n)?|(?:\\r?\\n|$))#imux', $rowPattern);
+ $output = \rtrim(\preg_replace($pattern, '\\1' . $break, $text), $break);
+ return \str_replace(' ' . $break, $break, $output);
+ }
+}
diff --git a/vendor/symfony/console/Helper/ProcessHelper.php b/vendor/symfony/console/Helper/ProcessHelper.php
new file mode 100644
index 00000000..0cb78471
--- /dev/null
+++ b/vendor/symfony/console/Helper/ProcessHelper.php
@@ -0,0 +1,116 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Helper;
+
+use ClassLeak202307\Symfony\Component\Console\Output\ConsoleOutputInterface;
+use ClassLeak202307\Symfony\Component\Console\Output\OutputInterface;
+use ClassLeak202307\Symfony\Component\Process\Exception\ProcessFailedException;
+use ClassLeak202307\Symfony\Component\Process\Process;
+/**
+ * The ProcessHelper class provides helpers to run external processes.
+ *
+ * @author Fabien Potencier
+ *
+ * @final
+ */
+class ProcessHelper extends Helper
+{
+ /**
+ * Runs an external process.
+ *
+ * @param mixed[]|\Symfony\Component\Process\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, 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 ($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()) {
+ $output->write($formatter->start(\spl_object_hash($process), $this->escapeString($process->getCommandLine())));
+ }
+ if ($output->isDebug()) {
+ $callback = $this->wrapCallback($output, $process, $callback);
+ }
+ $process->run($callback, $cmd);
+ if ($verbosity <= $output->getVerbosity()) {
+ $message = $process->isSuccessful() ? 'Command ran successfully' : \sprintf('%s Command did not run successfully', $process->getExitCode());
+ $output->write($formatter->stop(\spl_object_hash($process), $message, $process->isSuccessful()));
+ }
+ if (!$process->isSuccessful() && null !== $error) {
+ $output->writeln(\sprintf('%s', $this->escapeString($error)));
+ }
+ return $process;
+ }
+ /**
+ * Runs the process.
+ *
+ * This is identical to run() except that an exception is thrown if the process
+ * exits with a non-zero exit code.
+ *
+ * @param mixed[]|\Symfony\Component\Process\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, string $error = null, callable $callback = null) : Process
+ {
+ $process = $this->run($output, $cmd, $error, $callback);
+ if (!$process->isSuccessful()) {
+ throw new ProcessFailedException($process);
+ }
+ return $process;
+ }
+ /**
+ * Wraps a Process callback to add debugging output.
+ */
+ public function wrapCallback(OutputInterface $output, Process $process, callable $callback = null) : callable
+ {
+ if ($output instanceof ConsoleOutputInterface) {
+ $output = $output->getErrorOutput();
+ }
+ $formatter = $this->getHelperSet()->get('debug_formatter');
+ return function ($type, $buffer) use($output, $process, $callback, $formatter) {
+ $output->write($formatter->progress(\spl_object_hash($process), $this->escapeString($buffer), Process::ERR === $type));
+ if (null !== $callback) {
+ $callback($type, $buffer);
+ }
+ };
+ }
+ private function escapeString(string $str) : string
+ {
+ return \str_replace('<', '\\<', $str);
+ }
+ public function getName() : string
+ {
+ return 'process';
+ }
+}
diff --git a/vendor/symfony/console/Helper/ProgressBar.php b/vendor/symfony/console/Helper/ProgressBar.php
new file mode 100644
index 00000000..62dff417
--- /dev/null
+++ b/vendor/symfony/console/Helper/ProgressBar.php
@@ -0,0 +1,591 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Helper;
+
+use ClassLeak202307\Symfony\Component\Console\Cursor;
+use ClassLeak202307\Symfony\Component\Console\Exception\LogicException;
+use ClassLeak202307\Symfony\Component\Console\Output\ConsoleOutputInterface;
+use ClassLeak202307\Symfony\Component\Console\Output\ConsoleSectionOutput;
+use ClassLeak202307\Symfony\Component\Console\Output\OutputInterface;
+use ClassLeak202307\Symfony\Component\Console\Terminal;
+/**
+ * The ProgressBar provides helpers to display progress output.
+ *
+ * @author Fabien Potencier
+ * @author Chris Jones
+ */
+final class ProgressBar
+{
+ public const FORMAT_VERBOSE = 'verbose';
+ public const FORMAT_VERY_VERBOSE = 'very_verbose';
+ public const FORMAT_DEBUG = 'debug';
+ public const FORMAT_NORMAL = 'normal';
+ private const FORMAT_VERBOSE_NOMAX = 'verbose_nomax';
+ private const FORMAT_VERY_VERBOSE_NOMAX = 'very_verbose_nomax';
+ private const FORMAT_DEBUG_NOMAX = 'debug_nomax';
+ private const FORMAT_NORMAL_NOMAX = 'normal_nomax';
+ /**
+ * @var int
+ */
+ private $barWidth = 28;
+ /**
+ * @var string
+ */
+ private $barChar;
+ /**
+ * @var string
+ */
+ private $emptyBarChar = '-';
+ /**
+ * @var string
+ */
+ private $progressChar = '>';
+ /**
+ * @var string|null
+ */
+ private $format;
+ /**
+ * @var string|null
+ */
+ private $internalFormat;
+ /**
+ * @var int|null
+ */
+ private $redrawFreq = 1;
+ /**
+ * @var int
+ */
+ private $writeCount = 0;
+ /**
+ * @var float
+ */
+ private $lastWriteTime = 0;
+ /**
+ * @var float
+ */
+ private $minSecondsBetweenRedraws = 0;
+ /**
+ * @var float
+ */
+ private $maxSecondsBetweenRedraws = 1;
+ /**
+ * @var \Symfony\Component\Console\Output\OutputInterface
+ */
+ private $output;
+ /**
+ * @var int
+ */
+ private $step = 0;
+ /**
+ * @var int
+ */
+ private $startingStep = 0;
+ /**
+ * @var int|null
+ */
+ private $max;
+ /**
+ * @var int
+ */
+ private $startTime;
+ /**
+ * @var int
+ */
+ private $stepWidth;
+ /**
+ * @var float
+ */
+ private $percent = 0.0;
+ /**
+ * @var mixed[]
+ */
+ private $messages = [];
+ /**
+ * @var bool
+ */
+ private $overwrite = \true;
+ /**
+ * @var \Symfony\Component\Console\Terminal
+ */
+ private $terminal;
+ /**
+ * @var string|null
+ */
+ private $previousMessage;
+ /**
+ * @var \Symfony\Component\Console\Cursor
+ */
+ private $cursor;
+ /**
+ * @var mixed[]
+ */
+ private $placeholders = [];
+ /**
+ * @var mixed[]
+ */
+ private static $formatters;
+ /**
+ * @var mixed[]
+ */
+ private static $formats;
+ /**
+ * @param int $max Maximum steps (0 if unknown)
+ */
+ public function __construct(OutputInterface $output, int $max = 0, float $minSecondsBetweenRedraws = 1 / 25)
+ {
+ if ($output instanceof ConsoleOutputInterface) {
+ $output = $output->getErrorOutput();
+ }
+ $this->output = $output;
+ $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->redrawFreq = null;
+ }
+ $this->startTime = \time();
+ $this->cursor = new Cursor($output);
+ }
+ /**
+ * Sets a placeholder formatter for a given name, globally for all instances of ProgressBar.
+ *
+ * This method also allow you to override an existing placeholder.
+ *
+ * @param string $name The placeholder name (including the delimiter char like %)
+ * @param callable(ProgressBar):string $callable A PHP callable
+ */
+ public static function setPlaceholderFormatterDefinition(string $name, callable $callable) : void
+ {
+ self::$formatters = 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 %)
+ */
+ public static function getPlaceholderFormatterDefinition(string $name) : ?callable
+ {
+ self::$formatters = self::$formatters ?? self::initPlaceholderFormatters();
+ return self::$formatters[$name] ?? null;
+ }
+ /**
+ * Sets a placeholder formatter for a given name, for this instance only.
+ *
+ * @param callable(ProgressBar):string $callable A PHP callable
+ */
+ public function setPlaceholderFormatter(string $name, callable $callable) : void
+ {
+ $this->placeholders[$name] = $callable;
+ }
+ /**
+ * Gets the placeholder formatter for a given name.
+ *
+ * @param string $name The placeholder name (including the delimiter char like %)
+ */
+ public function getPlaceholderFormatter(string $name) : ?callable
+ {
+ return $this->placeholders[$name] ?? $this::getPlaceholderFormatterDefinition($name);
+ }
+ /**
+ * Sets a format for a given name.
+ *
+ * This method also allow you to override an existing format.
+ *
+ * @param string $name The format name
+ * @param string $format A format string
+ */
+ public static function setFormatDefinition(string $name, string $format) : void
+ {
+ self::$formats = self::$formats ?? self::initFormats();
+ self::$formats[$name] = $format;
+ }
+ /**
+ * Gets the format for a given name.
+ *
+ * @param string $name The format name
+ */
+ public static function getFormatDefinition(string $name) : ?string
+ {
+ self::$formats = self::$formats ?? self::initFormats();
+ return self::$formats[$name] ?? null;
+ }
+ /**
+ * Associates a text with a named placeholder.
+ *
+ * The text is displayed when the progress bar is rendered but only
+ * when the corresponding placeholder is part of the custom format line
+ * (by wrapping the name with %).
+ *
+ * @param string $message The text to associate with the placeholder
+ * @param string $name The name of the placeholder
+ */
+ public function setMessage(string $message, string $name = 'message') : void
+ {
+ $this->messages[$name] = $message;
+ }
+ public function getMessage(string $name = 'message') : string
+ {
+ return $this->messages[$name];
+ }
+ public function getStartTime() : int
+ {
+ return $this->startTime;
+ }
+ public function getMaxSteps() : int
+ {
+ return $this->max;
+ }
+ public function getProgress() : int
+ {
+ return $this->step;
+ }
+ private function getStepWidth() : int
+ {
+ return $this->stepWidth;
+ }
+ public function getProgressPercent() : float
+ {
+ return $this->percent;
+ }
+ public function getBarOffset() : float
+ {
+ return \floor($this->max ? $this->percent * $this->barWidth : (null === $this->redrawFreq ? (int) (\min(5, $this->barWidth / 15) * $this->writeCount) : $this->step) % $this->barWidth);
+ }
+ public function getEstimated() : float
+ {
+ if (0 === $this->step || $this->step === $this->startingStep) {
+ return 0;
+ }
+ return \round((\time() - $this->startTime) / ($this->step - $this->startingStep) * $this->max);
+ }
+ public function getRemaining() : float
+ {
+ if (!$this->step) {
+ return 0;
+ }
+ return \round((\time() - $this->startTime) / ($this->step - $this->startingStep) * ($this->max - $this->step));
+ }
+ public function setBarWidth(int $size) : void
+ {
+ $this->barWidth = \max(1, $size);
+ }
+ public function getBarWidth() : int
+ {
+ return $this->barWidth;
+ }
+ public function setBarCharacter(string $char) : void
+ {
+ $this->barChar = $char;
+ }
+ public function getBarCharacter() : string
+ {
+ return $this->barChar ?? ($this->max ? '=' : $this->emptyBarChar);
+ }
+ public function setEmptyBarCharacter(string $char) : void
+ {
+ $this->emptyBarChar = $char;
+ }
+ public function getEmptyBarCharacter() : string
+ {
+ return $this->emptyBarChar;
+ }
+ public function setProgressCharacter(string $char) : void
+ {
+ $this->progressChar = $char;
+ }
+ public function getProgressCharacter() : string
+ {
+ return $this->progressChar;
+ }
+ public function setFormat(string $format) : void
+ {
+ $this->format = null;
+ $this->internalFormat = $format;
+ }
+ /**
+ * Sets the redraw frequency.
+ *
+ * @param int|null $freq The frequency in steps
+ */
+ public function setRedrawFrequency(?int $freq) : void
+ {
+ $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_array($iterable) || $iterable instanceof \Countable ? \count($iterable) : 0));
+ foreach ($iterable as $key => $value) {
+ (yield $key => $value);
+ $this->advance();
+ }
+ $this->finish();
+ }
+ /**
+ * Starts the progress output.
+ *
+ * @param int|null $max Number of steps to complete the bar (0 if indeterminate), null to leave unchanged
+ * @param int $startAt The starting point of the bar (useful e.g. when resuming a previously started bar)
+ */
+ public function start(int $max = null, int $startAt = 0) : void
+ {
+ $this->startTime = \time();
+ $this->step = $startAt;
+ $this->startingStep = $startAt;
+ $startAt > 0 ? $this->setProgress($startAt) : ($this->percent = 0.0);
+ if (null !== $max) {
+ $this->setMaxSteps($max);
+ }
+ $this->display();
+ }
+ /**
+ * Advances the progress output X steps.
+ *
+ * @param int $step Number of steps to advance
+ */
+ public function advance(int $step = 1) : void
+ {
+ $this->setProgress($this->step + $step);
+ }
+ /**
+ * Sets whether to overwrite the progressbar, false for new line.
+ */
+ public function setOverwrite(bool $overwrite) : void
+ {
+ $this->overwrite = $overwrite;
+ }
+ public function setProgress(int $step) : void
+ {
+ if ($this->max && $step > $this->max) {
+ $this->max = $step;
+ } elseif ($step < 0) {
+ $step = 0;
+ }
+ $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;
+ $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) : void
+ {
+ $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() : void
+ {
+ if (!$this->max) {
+ $this->max = $this->step;
+ }
+ if ($this->step === $this->max && !$this->overwrite) {
+ // prevent double 100% output
+ return;
+ }
+ $this->setProgress($this->max);
+ }
+ /**
+ * Outputs the current progress string.
+ */
+ public function display() : void
+ {
+ if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
+ return;
+ }
+ if (null === $this->format) {
+ $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
+ }
+ $this->overwrite($this->buildLine());
+ }
+ /**
+ * Removes the progress bar from the current line.
+ *
+ * This is useful if you wish to write some output
+ * while a progress bar is running.
+ * Call display() to show the progress bar again.
+ */
+ public function clear() : void
+ {
+ if (!$this->overwrite) {
+ return;
+ }
+ if (null === $this->format) {
+ $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
+ }
+ $this->overwrite('');
+ }
+ private function setRealFormat(string $format) : void
+ {
+ // try to use the _nomax variant if available
+ if (!$this->max && null !== self::getFormatDefinition($format . '_nomax')) {
+ $this->format = self::getFormatDefinition($format . '_nomax');
+ } elseif (null !== self::getFormatDefinition($format)) {
+ $this->format = self::getFormatDefinition($format);
+ } else {
+ $this->format = $format;
+ }
+ }
+ /**
+ * Overwrites a previous message to the output.
+ */
+ private function overwrite(string $message) : void
+ {
+ if ($this->previousMessage === $message) {
+ return;
+ }
+ $originalMessage = $message;
+ if ($this->overwrite) {
+ 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();
+ }
+ $this->cursor->moveToColumn(1);
+ $this->cursor->clearLine();
+ }
+ }
+ } elseif ($this->step > 0) {
+ $message = \PHP_EOL . $message;
+ }
+ $this->previousMessage = $originalMessage;
+ $this->lastWriteTime = \microtime(\true);
+ $this->output->write($message);
+ ++$this->writeCount;
+ }
+ private function determineBestFormat() : string
+ {
+ switch ($this->output->getVerbosity()) {
+ case OutputInterface::VERBOSITY_VERBOSE:
+ return $this->max ? self::FORMAT_VERBOSE : self::FORMAT_VERBOSE_NOMAX;
+ case OutputInterface::VERBOSITY_VERY_VERBOSE:
+ return $this->max ? self::FORMAT_VERY_VERBOSE : self::FORMAT_VERY_VERBOSE_NOMAX;
+ case OutputInterface::VERBOSITY_DEBUG:
+ return $this->max ? self::FORMAT_DEBUG : self::FORMAT_DEBUG_NOMAX;
+ default:
+ return $this->max ? self::FORMAT_NORMAL : self::FORMAT_NORMAL_NOMAX;
+ }
+ }
+ private static function initPlaceholderFormatters() : array
+ {
+ 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::length(Helper::removeDecoration($output->getFormatter(), $bar->getProgressCharacter()));
+ $display .= $bar->getProgressCharacter() . \str_repeat($bar->getEmptyBarCharacter(), $emptyBars);
+ }
+ return $display;
+ }, 'elapsed' => function (self $bar) {
+ return Helper::formatTime(\time() - $bar->getStartTime());
+ }, '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.');
+ }
+ return Helper::formatTime($bar->getRemaining());
+ }, 'estimated' => function (self $bar) {
+ if (!$bar->getMaxSteps()) {
+ throw new LogicException('Unable to display the estimated time if the maximum number of steps is not set.');
+ }
+ return Helper::formatTime($bar->getEstimated());
+ }, 'memory' => function (self $bar) {
+ return Helper::formatMemory(\memory_get_usage(\true));
+ }, 'current' => function (self $bar) {
+ return \str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', \STR_PAD_LEFT);
+ }, 'max' => function (self $bar) {
+ return $bar->getMaxSteps();
+ }, 'percent' => function (self $bar) {
+ return \floor($bar->getProgressPercent() * 100);
+ }];
+ }
+ private static function initFormats() : array
+ {
+ return [self::FORMAT_NORMAL => ' %current%/%max% [%bar%] %percent:3s%%', self::FORMAT_NORMAL_NOMAX => ' %current% [%bar%]', self::FORMAT_VERBOSE => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%', self::FORMAT_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%', self::FORMAT_DEBUG => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%', self::FORMAT_DEBUG_NOMAX => ' %current% [%bar%] %elapsed:6s% %memory:6s%'];
+ }
+ private function buildLine() : string
+ {
+ \assert(null !== $this->format);
+ $regex = "{%([a-z\\-_]+)(?:\\:([^%]+))?%}i";
+ $callback = function ($matches) {
+ if ($formatter = $this->getPlaceholderFormatter($matches[1])) {
+ $text = $formatter($this, $this->output);
+ } elseif (isset($this->messages[$matches[1]])) {
+ $text = $this->messages[$matches[1]];
+ } else {
+ return $matches[0];
+ }
+ if (isset($matches[2])) {
+ $text = \sprintf('%' . $matches[2], $text);
+ }
+ return $text;
+ };
+ $line = \preg_replace_callback($regex, $callback, $this->format);
+ // gets string length for each sub line with multiline format
+ $linesLength = \array_map(function ($subLine) {
+ return Helper::width(Helper::removeDecoration($this->output->getFormatter(), \rtrim($subLine, "\r")));
+ }, \explode("\n", $line));
+ $linesWidth = \max($linesLength);
+ $terminalWidth = $this->terminal->getWidth();
+ if ($linesWidth <= $terminalWidth) {
+ return $line;
+ }
+ $this->setBarWidth($this->barWidth - $linesWidth + $terminalWidth);
+ return \preg_replace_callback($regex, $callback, $this->format);
+ }
+}
diff --git a/vendor/symfony/console/Helper/ProgressIndicator.php b/vendor/symfony/console/Helper/ProgressIndicator.php
new file mode 100644
index 00000000..b2430a30
--- /dev/null
+++ b/vendor/symfony/console/Helper/ProgressIndicator.php
@@ -0,0 +1,225 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Helper;
+
+use ClassLeak202307\Symfony\Component\Console\Exception\InvalidArgumentException;
+use ClassLeak202307\Symfony\Component\Console\Exception\LogicException;
+use ClassLeak202307\Symfony\Component\Console\Output\OutputInterface;
+/**
+ * @author Kevin Bond
+ */
+class ProgressIndicator
+{
+ private const FORMATS = ['normal' => ' %indicator% %message%', 'normal_no_ansi' => ' %message%', 'verbose' => ' %indicator% %message% (%elapsed:6s%)', 'verbose_no_ansi' => ' %message% (%elapsed:6s%)', 'very_verbose' => ' %indicator% %message% (%elapsed:6s%, %memory:6s%)', 'very_verbose_no_ansi' => ' %message% (%elapsed:6s%, %memory:6s%)'];
+ /**
+ * @var \Symfony\Component\Console\Output\OutputInterface
+ */
+ private $output;
+ /**
+ * @var int
+ */
+ private $startTime;
+ /**
+ * @var string|null
+ */
+ private $format;
+ /**
+ * @var string|null
+ */
+ private $message;
+ /**
+ * @var mixed[]
+ */
+ private $indicatorValues;
+ /**
+ * @var int
+ */
+ private $indicatorCurrent;
+ /**
+ * @var int
+ */
+ private $indicatorChangeInterval;
+ /**
+ * @var float
+ */
+ private $indicatorUpdateTime;
+ /**
+ * @var bool
+ */
+ private $started = \false;
+ /**
+ * @var array
+ */
+ private static $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;
+ $format = $format ?? $this->determineBestFormat();
+ $indicatorValues = $indicatorValues ?? ['-', '\\', '|', '/'];
+ $indicatorValues = \array_values($indicatorValues);
+ if (2 > \count($indicatorValues)) {
+ throw new InvalidArgumentException('Must have at least 2 indicator value characters.');
+ }
+ $this->format = self::getFormatDefinition($format);
+ $this->indicatorChangeInterval = $indicatorChangeInterval;
+ $this->indicatorValues = $indicatorValues;
+ $this->startTime = \time();
+ }
+ /**
+ * Sets the current indicator message.
+ *
+ * @return void
+ */
+ public function setMessage(?string $message)
+ {
+ $this->message = $message;
+ $this->display();
+ }
+ /**
+ * Starts the indicator output.
+ *
+ * @return void
+ */
+ public function start(string $message)
+ {
+ if ($this->started) {
+ throw new LogicException('Progress indicator already started.');
+ }
+ $this->message = $message;
+ $this->started = \true;
+ $this->startTime = \time();
+ $this->indicatorUpdateTime = $this->getCurrentTimeInMilliseconds() + $this->indicatorChangeInterval;
+ $this->indicatorCurrent = 0;
+ $this->display();
+ }
+ /**
+ * Advances the indicator.
+ *
+ * @return void
+ */
+ public function advance()
+ {
+ if (!$this->started) {
+ throw new LogicException('Progress indicator has not yet been started.');
+ }
+ if (!$this->output->isDecorated()) {
+ return;
+ }
+ $currentTime = $this->getCurrentTimeInMilliseconds();
+ if ($currentTime < $this->indicatorUpdateTime) {
+ return;
+ }
+ $this->indicatorUpdateTime = $currentTime + $this->indicatorChangeInterval;
+ ++$this->indicatorCurrent;
+ $this->display();
+ }
+ /**
+ * Finish the indicator with message.
+ *
+ * @return void
+ */
+ public function finish(string $message)
+ {
+ if (!$this->started) {
+ throw new LogicException('Progress indicator has not yet been started.');
+ }
+ $this->message = $message;
+ $this->display();
+ $this->output->writeln('');
+ $this->started = \false;
+ }
+ /**
+ * Gets the format for a given name.
+ */
+ public static function getFormatDefinition(string $name) : ?string
+ {
+ return self::FORMATS[$name] ?? null;
+ }
+ /**
+ * Sets a placeholder formatter for a given name.
+ *
+ * This method also allow you to override an existing placeholder.
+ *
+ * @return void
+ */
+ public static function setPlaceholderFormatterDefinition(string $name, callable $callable)
+ {
+ self::$formatters = self::$formatters ?? self::initPlaceholderFormatters();
+ self::$formatters[$name] = $callable;
+ }
+ /**
+ * Gets the placeholder formatter for a given name (including the delimiter char like %).
+ */
+ public static function getPlaceholderFormatterDefinition(string $name) : ?callable
+ {
+ self::$formatters = self::$formatters ?? self::initPlaceholderFormatters();
+ return self::$formatters[$name] ?? null;
+ }
+ private function display() : void
+ {
+ if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
+ return;
+ }
+ $this->overwrite(\preg_replace_callback("{%([a-z\\-_]+)(?:\\:([^%]+))?%}i", function ($matches) {
+ if ($formatter = self::getPlaceholderFormatterDefinition($matches[1])) {
+ return $formatter($this);
+ }
+ return $matches[0];
+ }, $this->format ?? ''));
+ }
+ private function determineBestFormat() : string
+ {
+ switch ($this->output->getVerbosity()) {
+ case OutputInterface::VERBOSITY_VERBOSE:
+ return $this->output->isDecorated() ? 'verbose' : 'verbose_no_ansi';
+ case OutputInterface::VERBOSITY_VERY_VERBOSE:
+ case OutputInterface::VERBOSITY_DEBUG:
+ return $this->output->isDecorated() ? 'very_verbose' : 'very_verbose_no_ansi';
+ default:
+ return $this->output->isDecorated() ? 'normal' : 'normal_no_ansi';
+ }
+ }
+ /**
+ * Overwrites a previous message to the output.
+ */
+ private function overwrite(string $message) : void
+ {
+ if ($this->output->isDecorated()) {
+ $this->output->write("\r\x1b[2K");
+ $this->output->write($message);
+ } else {
+ $this->output->writeln($message);
+ }
+ }
+ private function getCurrentTimeInMilliseconds() : float
+ {
+ return \round(\microtime(\true) * 1000);
+ }
+ /**
+ * @return array
+ */
+ private static function initPlaceholderFormatters() : array
+ {
+ return ['indicator' => function (self $indicator) {
+ return $indicator->indicatorValues[$indicator->indicatorCurrent % \count($indicator->indicatorValues)];
+ }, 'message' => function (self $indicator) {
+ return $indicator->message;
+ }, 'elapsed' => function (self $indicator) {
+ return Helper::formatTime(\time() - $indicator->startTime);
+ }, 'memory' => function () {
+ return Helper::formatMemory(\memory_get_usage(\true));
+ }];
+ }
+}
diff --git a/vendor/symfony/console/Helper/QuestionHelper.php b/vendor/symfony/console/Helper/QuestionHelper.php
new file mode 100644
index 00000000..3f6f5e32
--- /dev/null
+++ b/vendor/symfony/console/Helper/QuestionHelper.php
@@ -0,0 +1,517 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Helper;
+
+use ClassLeak202307\Symfony\Component\Console\Cursor;
+use ClassLeak202307\Symfony\Component\Console\Exception\MissingInputException;
+use ClassLeak202307\Symfony\Component\Console\Exception\RuntimeException;
+use ClassLeak202307\Symfony\Component\Console\Formatter\OutputFormatter;
+use ClassLeak202307\Symfony\Component\Console\Formatter\OutputFormatterStyle;
+use ClassLeak202307\Symfony\Component\Console\Input\InputInterface;
+use ClassLeak202307\Symfony\Component\Console\Input\StreamableInputInterface;
+use ClassLeak202307\Symfony\Component\Console\Output\ConsoleOutputInterface;
+use ClassLeak202307\Symfony\Component\Console\Output\ConsoleSectionOutput;
+use ClassLeak202307\Symfony\Component\Console\Output\OutputInterface;
+use ClassLeak202307\Symfony\Component\Console\Question\ChoiceQuestion;
+use ClassLeak202307\Symfony\Component\Console\Question\Question;
+use ClassLeak202307\Symfony\Component\Console\Terminal;
+use function ClassLeak202307\Symfony\Component\String\s;
+/**
+ * The QuestionHelper class provides helpers to interact with the user.
+ *
+ * @author Fabien Potencier
+ */
+class QuestionHelper extends Helper
+{
+ /**
+ * @var resource|null
+ */
+ private $inputStream;
+ /**
+ * @var bool
+ */
+ private static $stty = \true;
+ /**
+ * @var bool
+ */
+ private static $stdinIsInteractive;
+ /**
+ * Asks a question to the user.
+ *
+ * @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)
+ {
+ if ($output instanceof ConsoleOutputInterface) {
+ $output = $output->getErrorOutput();
+ }
+ if (!$input->isInteractive()) {
+ return $this->getDefaultAnswer($question);
+ }
+ if ($input instanceof StreamableInputInterface && ($stream = $input->getStream())) {
+ $this->inputStream = $stream;
+ }
+ 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;
+ }
+ }
+ public function getName() : string
+ {
+ return 'question';
+ }
+ /**
+ * Prevents usage of stty.
+ *
+ * @return void
+ */
+ public static function disableStty()
+ {
+ self::$stty = \false;
+ }
+ /**
+ * Asks the question to the user.
+ *
+ * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden
+ * @return mixed
+ */
+ private function doAsk(OutputInterface $output, Question $question)
+ {
+ $this->writePrompt($output, $question);
+ $inputStream = $this->inputStream ?: \STDIN;
+ $autocomplete = $question->getAutocompleterCallback();
+ if (null === $autocomplete || !self::$stty || !Terminal::hasSttyAvailable()) {
+ $ret = \false;
+ if ($question->isHidden()) {
+ try {
+ $hiddenResponse = $this->getHiddenResponse($output, $inputStream, $question->isTrimmable());
+ $ret = $question->isTrimmable() ? \trim($hiddenResponse) : $hiddenResponse;
+ } catch (RuntimeException $e) {
+ if (!$question->isHiddenFallback()) {
+ throw $e;
+ }
+ }
+ }
+ if (\false === $ret) {
+ $isBlocked = \stream_get_meta_data($inputStream)['blocked'] ?? \true;
+ if (!$isBlocked) {
+ \stream_set_blocking($inputStream, \true);
+ }
+ $ret = $this->readInput($inputStream, $question);
+ if (!$isBlocked) {
+ \stream_set_blocking($inputStream, \false);
+ }
+ if (\false === $ret) {
+ throw new MissingInputException('Aborted.');
+ }
+ if ($question->isTrimmable()) {
+ $ret = \trim($ret);
+ }
+ }
+ } else {
+ $autocomplete = $this->autocomplete($output, $question, $inputStream, $autocomplete);
+ $ret = $question->isTrimmable() ? \trim($autocomplete) : $autocomplete;
+ }
+ if ($output instanceof ConsoleSectionOutput) {
+ $output->addContent('');
+ // add EOL to the question
+ $output->addContent($ret);
+ }
+ $ret = \strlen($ret) > 0 ? $ret : $question->getDefault();
+ if ($normalizer = $question->getNormalizer()) {
+ return $normalizer($ret);
+ }
+ return $ret;
+ }
+ /**
+ * @return mixed
+ */
+ private function getDefaultAnswer(Question $question)
+ {
+ $default = $question->getDefault();
+ if (null === $default) {
+ return $default;
+ }
+ if ($validator = $question->getValidator()) {
+ return \call_user_func($validator, $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.
+ *
+ * @return void
+ */
+ protected function writePrompt(OutputInterface $output, Question $question)
+ {
+ $message = $question->getQuestion();
+ if ($question instanceof ChoiceQuestion) {
+ $output->writeln(\array_merge([$question->getQuestion()], $this->formatChoiceQuestionChoices($question, 'info')));
+ $message = $question->getPrompt();
+ }
+ $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.
+ *
+ * @return void
+ */
+ protected function writeError(OutputInterface $output, \Exception $error)
+ {
+ if (null !== $this->getHelperSet() && $this->getHelperSet()->has('formatter')) {
+ $message = $this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error');
+ } else {
+ $message = '' . $error->getMessage() . '';
+ }
+ $output->writeln($message);
+ }
+ /**
+ * Autocompletes a question.
+ *
+ * @param resource $inputStream
+ */
+ private function autocomplete(OutputInterface $output, Question $question, $inputStream, callable $autocomplete) : string
+ {
+ $cursor = new Cursor($output, $inputStream);
+ $fullChoice = '';
+ $ret = '';
+ $i = 0;
+ $ofs = -1;
+ $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');
+ // Add highlighted text style
+ $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white'));
+ // Read a keypress
+ while (!\feof($inputStream)) {
+ while ($isStdin && 0 === @\stream_select($r, $w, $w, 0, 100)) {
+ // Give signal handlers a chance to run
+ $r = [$inputStream];
+ }
+ $c = \fread($inputStream, 1);
+ // as opposed to fgets(), fread() returns an empty string when the stream content is empty, not false.
+ if (\false === $c || '' === $ret && '' === $c && null === $question->getDefault()) {
+ \shell_exec('stty ' . $sttyMode);
+ throw new MissingInputException('Aborted.');
+ } elseif ("" === $c) {
+ // Backspace Character
+ if (0 === $numMatches && 0 !== $i) {
+ --$i;
+ $cursor->moveLeft(s($fullChoice)->slice(-1)->width(\false));
+ $fullChoice = self::substr($fullChoice, 0, $i);
+ }
+ if (0 === $i) {
+ $ofs = -1;
+ $matches = $autocomplete($ret);
+ $numMatches = \count($matches);
+ } else {
+ $numMatches = 0;
+ }
+ // Pop the last character off the end of our string
+ $ret = self::substr($ret, 0, $i);
+ } elseif ("\x1b" === $c) {
+ // Did we read an escape sequence?
+ $c .= \fread($inputStream, 2);
+ // A = Up Arrow. B = Down Arrow
+ if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) {
+ if ('A' === $c[2] && -1 === $ofs) {
+ $ofs = 0;
+ }
+ if (0 === $numMatches) {
+ continue;
+ }
+ $ofs += 'A' === $c[2] ? -1 : 1;
+ $ofs = ($numMatches + $ofs) % $numMatches;
+ }
+ } elseif (\ord($c) < 32) {
+ if ("\t" === $c || "\n" === $c) {
+ if ($numMatches > 0 && -1 !== $ofs) {
+ $ret = (string) $matches[$ofs];
+ // Echo out remaining chars for current match
+ $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 || \strncmp($match, $ret, \strlen($ret)) === 0;
+ });
+ $numMatches = \count($matches);
+ $ofs = -1;
+ }
+ if ("\n" === $c) {
+ $output->write($c);
+ break;
+ }
+ $numMatches = 0;
+ }
+ 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($ret) as $value) {
+ // If typed characters match the beginning chunk of value (e.g. [AcmeDe]moBundle)
+ if (\strncmp($value, $tempRet, \strlen($tempRet)) === 0) {
+ $matches[$numMatches++] = $value;
+ }
+ }
+ }
+ $cursor->clearLineAfter();
+ if ($numMatches > 0 && -1 !== $ofs) {
+ $cursor->savePosition();
+ // Write highlighted text, complete the partially entered response
+ $charactersEntered = \strlen(\trim($this->mostRecentlyEnteredValue($fullChoice)));
+ $output->write('' . OutputFormatter::escapeTrailingBackslash(\substr($matches[$ofs], $charactersEntered)) . '');
+ $cursor->restorePosition();
+ }
+ }
+ // Reset stty so it behaves normally again
+ \shell_exec('stty ' . $sttyMode);
+ return $fullChoice;
+ }
+ private function mostRecentlyEnteredValue(string $entered) : string
+ {
+ // Determine the most recent value that the user entered
+ if (\strpos($entered, ',') === \false) {
+ return $entered;
+ }
+ $choices = \explode(',', $entered);
+ if ('' !== ($lastChoice = \trim($choices[\count($choices) - 1]))) {
+ return $lastChoice;
+ }
+ return $entered;
+ }
+ /**
+ * Gets a hidden response from user.
+ *
+ * @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, bool $trimmable = \true) : string
+ {
+ if ('\\' === \DIRECTORY_SEPARATOR) {
+ $exe = __DIR__ . '/../Resources/bin/hiddeninput.exe';
+ // handle code running from a phar
+ if (\strncmp(__FILE__, 'phar:', \strlen('phar:')) === 0) {
+ $tmpExe = \sys_get_temp_dir() . '/hiddeninput.exe';
+ \copy($exe, $tmpExe);
+ $exe = $tmpExe;
+ }
+ $sExec = \shell_exec('"' . $exe . '"');
+ $value = $trimmable ? \rtrim($sExec) : $sExec;
+ $output->writeln('');
+ if (isset($tmpExe)) {
+ \unlink($tmpExe);
+ }
+ return $value;
+ }
+ if (self::$stty && Terminal::hasSttyAvailable()) {
+ $sttyMode = \shell_exec('stty -g');
+ \shell_exec('stty -echo');
+ } elseif ($this->isInteractiveInput($inputStream)) {
+ throw new RuntimeException('Unable to hide the response.');
+ }
+ $value = \fgets($inputStream, 4096);
+ if (4095 === \strlen($value)) {
+ $errOutput = $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output;
+ $errOutput->warning('The value was possibly truncated by your shell or terminal emulator');
+ }
+ 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;
+ }
+ /**
+ * Validates an attempt.
+ *
+ * @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
+ * @return mixed
+ */
+ private function validateAttempts(callable $interviewer, OutputInterface $output, Question $question)
+ {
+ $error = null;
+ $attempts = $question->getMaxAttempts();
+ while (null === $attempts || $attempts--) {
+ if (null !== $error) {
+ $this->writeError($output, $error);
+ }
+ try {
+ return $question->getValidator()($interviewer());
+ } catch (RuntimeException $e) {
+ throw $e;
+ } catch (\Exception $error) {
+ }
+ }
+ throw $error;
+ }
+ private function isInteractiveInput($inputStream) : bool
+ {
+ if ('php://stdin' !== (\stream_get_meta_data($inputStream)['uri'] ?? null)) {
+ return \false;
+ }
+ if (isset(self::$stdinIsInteractive)) {
+ return self::$stdinIsInteractive;
+ }
+ 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('shell_exec')) {
+ return self::$stdinIsInteractive = \true;
+ }
+ return self::$stdinIsInteractive = (bool) \shell_exec('stty 2> ' . ('\\' === \DIRECTORY_SEPARATOR ? 'NUL' : '/dev/null'));
+ }
+ /**
+ * Reads one or more lines of input and returns what is read.
+ *
+ * @param resource $inputStream The handler resource
+ * @param Question $question The question being asked
+ * @return string|false
+ */
+ private function readInput($inputStream, Question $question)
+ {
+ if (!$question->isMultiline()) {
+ $cp = $this->setIOCodepage();
+ $ret = \fgets($inputStream, 4096);
+ return $this->resetIOCodepage($cp, $ret);
+ }
+ $multiLineStreamReader = $this->cloneInputStream($inputStream);
+ if (null === $multiLineStreamReader) {
+ return \false;
+ }
+ $ret = '';
+ $cp = $this->setIOCodepage();
+ while (\false !== ($char = \fgetc($multiLineStreamReader))) {
+ if (\PHP_EOL === "{$ret}{$char}") {
+ break;
+ }
+ $ret .= $char;
+ }
+ return $this->resetIOCodepage($cp, $ret);
+ }
+ 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.
+ * @param string|false $input
+ * @return string|false
+ */
+ private function resetIOCodepage(int $cp, $input)
+ {
+ 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 $input;
+ }
+ /**
+ * Clones an input stream in order to act on one instance of the same
+ * stream without affecting the other instance.
+ *
+ * @param resource $inputStream The handler resource
+ *
+ * @return resource|null The cloned resource, null in case it could not be cloned
+ */
+ private function cloneInputStream($inputStream)
+ {
+ $streamMetaData = \stream_get_meta_data($inputStream);
+ $seekable = $streamMetaData['seekable'] ?? \false;
+ $mode = $streamMetaData['mode'] ?? 'rb';
+ $uri = $streamMetaData['uri'] ?? null;
+ if (null === $uri) {
+ return null;
+ }
+ $cloneStream = \fopen($uri, $mode);
+ // For seekable and writable streams, add all the same data to the
+ // cloned stream and then seek to the same offset.
+ if (\true === $seekable && !\in_array($mode, ['r', 'rb', 'rt'])) {
+ $offset = \ftell($inputStream);
+ \rewind($inputStream);
+ \stream_copy_to_stream($inputStream, $cloneStream);
+ \fseek($inputStream, $offset);
+ \fseek($cloneStream, $offset);
+ }
+ return $cloneStream;
+ }
+}
diff --git a/vendor/symfony/console/Helper/SymfonyQuestionHelper.php b/vendor/symfony/console/Helper/SymfonyQuestionHelper.php
new file mode 100644
index 00000000..3f9e0cca
--- /dev/null
+++ b/vendor/symfony/console/Helper/SymfonyQuestionHelper.php
@@ -0,0 +1,85 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Helper;
+
+use ClassLeak202307\Symfony\Component\Console\Formatter\OutputFormatter;
+use ClassLeak202307\Symfony\Component\Console\Output\OutputInterface;
+use ClassLeak202307\Symfony\Component\Console\Question\ChoiceQuestion;
+use ClassLeak202307\Symfony\Component\Console\Question\ConfirmationQuestion;
+use ClassLeak202307\Symfony\Component\Console\Question\Question;
+use ClassLeak202307\Symfony\Component\Console\Style\SymfonyStyle;
+/**
+ * Symfony Style Guide compliant question helper.
+ *
+ * @author Kevin Bond
+ */
+class SymfonyQuestionHelper extends QuestionHelper
+{
+ /**
+ * @return void
+ */
+ protected function writePrompt(OutputInterface $output, Question $question)
+ {
+ $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(' %s:', $text);
+ break;
+ case $question instanceof ConfirmationQuestion:
+ $text = \sprintf(' %s (yes/no) [%s]:', $text, $default ? 'yes' : 'no');
+ break;
+ case $question instanceof ChoiceQuestion && $question->isMultiselect():
+ $choices = $question->getChoices();
+ $default = \explode(',', $default);
+ foreach ($default as $key => $value) {
+ $default[$key] = $choices[\trim($value)];
+ }
+ $text = \sprintf(' %s [%s]:', $text, OutputFormatter::escape(\implode(', ', $default)));
+ break;
+ case $question instanceof ChoiceQuestion:
+ $choices = $question->getChoices();
+ $text = \sprintf(' %s [%s]:', $text, OutputFormatter::escape($choices[$default] ?? $default));
+ break;
+ default:
+ $text = \sprintf(' %s [%s]:', $text, OutputFormatter::escape($default));
+ }
+ $output->writeln($text);
+ $prompt = ' > ';
+ if ($question instanceof ChoiceQuestion) {
+ $output->writeln($this->formatChoiceQuestionChoices($question, 'comment'));
+ $prompt = $question->getPrompt();
+ }
+ $output->write($prompt);
+ }
+ /**
+ * @return void
+ */
+ protected function writeError(OutputInterface $output, \Exception $error)
+ {
+ if ($output instanceof SymfonyStyle) {
+ $output->newLine();
+ $output->error($error->getMessage());
+ return;
+ }
+ parent::writeError($output, $error);
+ }
+ private function getEofShortcut() : string
+ {
+ if ('Windows' === \PHP_OS_FAMILY) {
+ return 'Ctrl+Z then Enter';
+ }
+ return 'Ctrl+D';
+ }
+}
diff --git a/vendor/symfony/console/Helper/Table.php b/vendor/symfony/console/Helper/Table.php
new file mode 100644
index 00000000..fc8ccce4
--- /dev/null
+++ b/vendor/symfony/console/Helper/Table.php
@@ -0,0 +1,801 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Helper;
+
+use ClassLeak202307\Symfony\Component\Console\Exception\InvalidArgumentException;
+use ClassLeak202307\Symfony\Component\Console\Exception\RuntimeException;
+use ClassLeak202307\Symfony\Component\Console\Formatter\OutputFormatter;
+use ClassLeak202307\Symfony\Component\Console\Formatter\WrappableOutputFormatterInterface;
+use ClassLeak202307\Symfony\Component\Console\Output\ConsoleSectionOutput;
+use ClassLeak202307\Symfony\Component\Console\Output\OutputInterface;
+/**
+ * Provides helpers to display a table.
+ *
+ * @author Fabien Potencier
+ * @author Саша Стаменковић
+ * @author Abdellatif Ait boudad
+ * @author Max Grigorian
+ * @author Dany Maillard
+ */
+class Table
+{
+ private const SEPARATOR_TOP = 0;
+ private const SEPARATOR_TOP_BOTTOM = 1;
+ private const SEPARATOR_MID = 2;
+ private const SEPARATOR_BOTTOM = 3;
+ private const BORDER_OUTSIDE = 0;
+ private const BORDER_INSIDE = 1;
+ private const DISPLAY_ORIENTATION_DEFAULT = 'default';
+ private const DISPLAY_ORIENTATION_HORIZONTAL = 'horizontal';
+ private const DISPLAY_ORIENTATION_VERTICAL = 'vertical';
+ /**
+ * @var string|null
+ */
+ private $headerTitle;
+ /**
+ * @var string|null
+ */
+ private $footerTitle;
+ /**
+ * @var mixed[]
+ */
+ private $headers = [];
+ /**
+ * @var mixed[]
+ */
+ private $rows = [];
+ /**
+ * @var mixed[]
+ */
+ private $effectiveColumnWidths = [];
+ /**
+ * @var int
+ */
+ private $numberOfColumns;
+ /**
+ * @var \Symfony\Component\Console\Output\OutputInterface
+ */
+ private $output;
+ /**
+ * @var \Symfony\Component\Console\Helper\TableStyle
+ */
+ private $style;
+ /**
+ * @var mixed[]
+ */
+ private $columnStyles = [];
+ /**
+ * @var mixed[]
+ */
+ private $columnWidths = [];
+ /**
+ * @var mixed[]
+ */
+ private $columnMaxWidths = [];
+ /**
+ * @var bool
+ */
+ private $rendered = \false;
+ /**
+ * @var string
+ */
+ private $displayOrientation = self::DISPLAY_ORIENTATION_DEFAULT;
+ /**
+ * @var mixed[]
+ */
+ private static $styles;
+ public function __construct(OutputInterface $output)
+ {
+ $this->output = $output;
+ self::$styles = self::$styles ?? self::initStyles();
+ $this->setStyle('default');
+ }
+ /**
+ * Sets a style definition.
+ *
+ * @return void
+ */
+ public static function setStyleDefinition(string $name, TableStyle $style)
+ {
+ self::$styles = self::$styles ?? self::initStyles();
+ self::$styles[$name] = $style;
+ }
+ /**
+ * Gets a style definition by name.
+ */
+ public static function getStyleDefinition(string $name) : TableStyle
+ {
+ self::$styles = self::$styles ?? self::initStyles();
+ if (!isset(self::$styles[$name])) {
+ throw new InvalidArgumentException(\sprintf('Style "%s" is not defined.', $name));
+ }
+ return self::$styles[$name];
+ }
+ /**
+ * Sets table style.
+ *
+ * @return $this
+ * @param \Symfony\Component\Console\Helper\TableStyle|string $name
+ */
+ public function setStyle($name)
+ {
+ $this->style = $this->resolveStyle($name);
+ return $this;
+ }
+ /**
+ * Gets the current table style.
+ */
+ public function getStyle() : TableStyle
+ {
+ return $this->style;
+ }
+ /**
+ * Sets table column style.
+ *
+ * @param TableStyle|string $name The style name or a TableStyle instance
+ *
+ * @return $this
+ */
+ public function setColumnStyle(int $columnIndex, $name)
+ {
+ $this->columnStyles[$columnIndex] = $this->resolveStyle($name);
+ return $this;
+ }
+ /**
+ * Gets the current style for a column.
+ *
+ * If style was not set, it returns the global table style.
+ */
+ public function getColumnStyle(int $columnIndex) : TableStyle
+ {
+ return $this->columnStyles[$columnIndex] ?? $this->getStyle();
+ }
+ /**
+ * Sets the minimum width of a column.
+ *
+ * @return $this
+ */
+ public function setColumnWidth(int $columnIndex, int $width)
+ {
+ $this->columnWidths[$columnIndex] = $width;
+ return $this;
+ }
+ /**
+ * Sets the minimum width of all columns.
+ *
+ * @return $this
+ */
+ public function setColumnWidths(array $widths)
+ {
+ $this->columnWidths = [];
+ foreach ($widths as $index => $width) {
+ $this->setColumnWidth($index, $width);
+ }
+ return $this;
+ }
+ /**
+ * Sets the maximum width of a column.
+ *
+ * Any cell within this column which contents exceeds the specified width will be wrapped into multiple lines, while
+ * formatted strings are preserved.
+ *
+ * @return $this
+ */
+ public function setColumnMaxWidth(int $columnIndex, int $width)
+ {
+ if (!$this->output->getFormatter() instanceof WrappableOutputFormatterInterface) {
+ throw new \LogicException(\sprintf('Setting a maximum column width is only supported when using a "%s" formatter, got "%s".', WrappableOutputFormatterInterface::class, \get_debug_type($this->output->getFormatter())));
+ }
+ $this->columnMaxWidths[$columnIndex] = $width;
+ return $this;
+ }
+ /**
+ * @return $this
+ */
+ public function setHeaders(array $headers)
+ {
+ $headers = \array_values($headers);
+ if ($headers && !\is_array($headers[0])) {
+ $headers = [$headers];
+ }
+ $this->headers = $headers;
+ return $this;
+ }
+ /**
+ * @return $this
+ */
+ public function setRows(array $rows)
+ {
+ $this->rows = [];
+ return $this->addRows($rows);
+ }
+ /**
+ * @return $this
+ */
+ public function addRows(array $rows)
+ {
+ foreach ($rows as $row) {
+ $this->addRow($row);
+ }
+ return $this;
+ }
+ /**
+ * @return $this
+ * @param \Symfony\Component\Console\Helper\TableSeparator|mixed[] $row
+ */
+ public function addRow($row)
+ {
+ if ($row instanceof TableSeparator) {
+ $this->rows[] = $row;
+ return $this;
+ }
+ $this->rows[] = \array_values($row);
+ return $this;
+ }
+ /**
+ * Adds a row to the table, and re-renders the table.
+ *
+ * @return $this
+ * @param \Symfony\Component\Console\Helper\TableSeparator|mixed[] $row
+ */
+ public function appendRow($row)
+ {
+ if (!$this->output instanceof ConsoleSectionOutput) {
+ throw new RuntimeException(\sprintf('Output should be an instance of "%s" when calling "%s".', ConsoleSectionOutput::class, __METHOD__));
+ }
+ if ($this->rendered) {
+ $this->output->clear($this->calculateRowCount());
+ }
+ $this->addRow($row);
+ $this->render();
+ return $this;
+ }
+ /**
+ * @return $this
+ * @param int|string $column
+ */
+ public function setRow($column, array $row)
+ {
+ $this->rows[$column] = $row;
+ return $this;
+ }
+ /**
+ * @return $this
+ */
+ public function setHeaderTitle(?string $title)
+ {
+ $this->headerTitle = $title;
+ return $this;
+ }
+ /**
+ * @return $this
+ */
+ public function setFooterTitle(?string $title)
+ {
+ $this->footerTitle = $title;
+ return $this;
+ }
+ /**
+ * @return $this
+ */
+ public function setHorizontal(bool $horizontal = \true)
+ {
+ $this->displayOrientation = $horizontal ? self::DISPLAY_ORIENTATION_HORIZONTAL : self::DISPLAY_ORIENTATION_DEFAULT;
+ return $this;
+ }
+ /**
+ * @return $this
+ */
+ public function setVertical(bool $vertical = \true)
+ {
+ $this->displayOrientation = $vertical ? self::DISPLAY_ORIENTATION_VERTICAL : self::DISPLAY_ORIENTATION_DEFAULT;
+ return $this;
+ }
+ /**
+ * Renders table to output.
+ *
+ * Example:
+ *
+ * +---------------+-----------------------+------------------+
+ * | ISBN | Title | Author |
+ * +---------------+-----------------------+------------------+
+ * | 99921-58-10-7 | Divine Comedy | Dante Alighieri |
+ * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |
+ * | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien |
+ * +---------------+-----------------------+------------------+
+ *
+ * @return void
+ */
+ public function render()
+ {
+ $divider = new TableSeparator();
+ $isCellWithColspan = static function ($cell) {
+ return $cell instanceof TableCell && $cell->getColspan() >= 2;
+ };
+ $horizontal = self::DISPLAY_ORIENTATION_HORIZONTAL === $this->displayOrientation;
+ $vertical = self::DISPLAY_ORIENTATION_VERTICAL === $this->displayOrientation;
+ $rows = [];
+ if ($horizontal) {
+ foreach ($this->headers[0] ?? [] as $i => $header) {
+ $rows[$i] = [$header];
+ foreach ($this->rows as $row) {
+ if ($row instanceof TableSeparator) {
+ continue;
+ }
+ if (isset($row[$i])) {
+ $rows[$i][] = $row[$i];
+ } elseif ($isCellWithColspan($rows[$i][0])) {
+ // Noop, there is a "title"
+ } else {
+ $rows[$i][] = null;
+ }
+ }
+ }
+ } elseif ($vertical) {
+ $formatter = $this->output->getFormatter();
+ $maxHeaderLength = \array_reduce($this->headers[0] ?? [], static function ($max, $header) use($formatter) {
+ return \max($max, Helper::width(Helper::removeDecoration($formatter, $header)));
+ }, 0);
+ foreach ($this->rows as $row) {
+ if ($row instanceof TableSeparator) {
+ continue;
+ }
+ if ($rows) {
+ $rows[] = [$divider];
+ }
+ $containsColspan = \false;
+ foreach ($row as $cell) {
+ if ($containsColspan = $isCellWithColspan($cell)) {
+ break;
+ }
+ }
+ $headers = $this->headers[0] ?? [];
+ $maxRows = \max(\count($headers), \count($row));
+ for ($i = 0; $i < $maxRows; ++$i) {
+ $cell = (string) ($row[$i] ?? '');
+ if ($headers && !$containsColspan) {
+ $rows[] = [\sprintf('%s>: %s', \str_pad($headers[$i] ?? '', $maxHeaderLength, ' ', \STR_PAD_LEFT), $cell)];
+ } elseif ('' !== $cell) {
+ $rows[] = [$cell];
+ }
+ }
+ }
+ } else {
+ $rows = \array_merge($this->headers, [$divider], $this->rows);
+ }
+ $this->calculateNumberOfColumns($rows);
+ $rowGroups = $this->buildTableRows($rows);
+ $this->calculateColumnsWidth($rowGroups);
+ $isHeader = !$horizontal;
+ $isFirstRow = $horizontal;
+ $hasTitle = (bool) $this->headerTitle;
+ foreach ($rowGroups as $rowGroup) {
+ $isHeaderSeparatorRendered = \false;
+ foreach ($rowGroup as $row) {
+ if ($divider === $row) {
+ $isHeader = \false;
+ $isFirstRow = \true;
+ continue;
+ }
+ if ($row instanceof TableSeparator) {
+ $this->renderRowSeparator();
+ continue;
+ }
+ if (!$row) {
+ continue;
+ }
+ if ($isHeader && !$isHeaderSeparatorRendered) {
+ $this->renderRowSeparator($isHeader ? self::SEPARATOR_TOP : self::SEPARATOR_TOP_BOTTOM, $hasTitle ? $this->headerTitle : null, $hasTitle ? $this->style->getHeaderTitleFormat() : null);
+ $hasTitle = \false;
+ $isHeaderSeparatorRendered = \true;
+ }
+ if ($isFirstRow) {
+ $this->renderRowSeparator($isHeader ? self::SEPARATOR_TOP : self::SEPARATOR_TOP_BOTTOM, $hasTitle ? $this->headerTitle : null, $hasTitle ? $this->style->getHeaderTitleFormat() : null);
+ $isFirstRow = \false;
+ $hasTitle = \false;
+ }
+ if ($vertical) {
+ $isHeader = \false;
+ $isFirstRow = \false;
+ }
+ if ($horizontal) {
+ $this->renderRow($row, $this->style->getCellRowFormat(), $this->style->getCellHeaderFormat());
+ } else {
+ $this->renderRow($row, $isHeader ? $this->style->getCellHeaderFormat() : $this->style->getCellRowFormat());
+ }
+ }
+ }
+ $this->renderRowSeparator(self::SEPARATOR_BOTTOM, $this->footerTitle, $this->style->getFooterTitleFormat());
+ $this->cleanup();
+ $this->rendered = \true;
+ }
+ /**
+ * Renders horizontal header separator.
+ *
+ * Example:
+ *
+ * +-----+-----------+-------+
+ */
+ private function renderRowSeparator(int $type = self::SEPARATOR_MID, string $title = null, string $titleFormat = null) : void
+ {
+ if (!($count = $this->numberOfColumns)) {
+ return;
+ }
+ $borders = $this->style->getBorderChars();
+ if (!$borders[0] && !$borders[2] && !$this->style->getCrossingChar()) {
+ return;
+ }
+ $crossings = $this->style->getCrossingChars();
+ if (self::SEPARATOR_MID === $type) {
+ [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[2], $crossings[8], $crossings[0], $crossings[4]];
+ } elseif (self::SEPARATOR_TOP === $type) {
+ [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[0], $crossings[1], $crossings[2], $crossings[3]];
+ } elseif (self::SEPARATOR_TOP_BOTTOM === $type) {
+ [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[0], $crossings[9], $crossings[10], $crossings[11]];
+ } else {
+ [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[0], $crossings[7], $crossings[6], $crossings[5]];
+ }
+ $markup = $leftChar;
+ for ($column = 0; $column < $count; ++$column) {
+ $markup .= \str_repeat($horizontal, $this->effectiveColumnWidths[$column]);
+ $markup .= $column === $count - 1 ? $rightChar : $midChar;
+ }
+ if (null !== $title) {
+ $titleLength = Helper::width(Helper::removeDecoration($formatter = $this->output->getFormatter(), $formattedTitle = \sprintf($titleFormat, $title)));
+ $markupLength = Helper::width($markup);
+ if ($titleLength > ($limit = $markupLength - 4)) {
+ $titleLength = $limit;
+ $formatLength = Helper::width(Helper::removeDecoration($formatter, \sprintf($titleFormat, '')));
+ $formattedTitle = \sprintf($titleFormat, Helper::substr($title, 0, $limit - $formatLength - 3) . '...');
+ }
+ $titleStart = \intdiv($markupLength - $titleLength, 2);
+ if (\false === \mb_detect_encoding($markup, null, \true)) {
+ $markup = \substr_replace($markup, $formattedTitle, $titleStart, $titleLength);
+ } else {
+ $markup = \mb_substr($markup, 0, $titleStart) . $formattedTitle . \mb_substr($markup, $titleStart + $titleLength);
+ }
+ }
+ $this->output->writeln(\sprintf($this->style->getBorderFormat(), $markup));
+ }
+ /**
+ * Renders vertical column separator.
+ */
+ private function renderColumnSeparator(int $type = self::BORDER_OUTSIDE) : string
+ {
+ $borders = $this->style->getBorderChars();
+ return \sprintf($this->style->getBorderFormat(), self::BORDER_OUTSIDE === $type ? $borders[1] : $borders[3]);
+ }
+ /**
+ * Renders table row.
+ *
+ * Example:
+ *
+ * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |
+ */
+ private function renderRow(array $row, string $cellFormat, string $firstCellFormat = null) : void
+ {
+ $rowContent = $this->renderColumnSeparator(self::BORDER_OUTSIDE);
+ $columns = $this->getRowColumns($row);
+ $last = \count($columns) - 1;
+ foreach ($columns as $i => $column) {
+ if ($firstCellFormat && 0 === $i) {
+ $rowContent .= $this->renderCell($row, $column, $firstCellFormat);
+ } else {
+ $rowContent .= $this->renderCell($row, $column, $cellFormat);
+ }
+ $rowContent .= $this->renderColumnSeparator($last === $i ? self::BORDER_OUTSIDE : self::BORDER_INSIDE);
+ }
+ $this->output->writeln($rowContent);
+ }
+ /**
+ * Renders table cell with padding.
+ */
+ private function renderCell(array $row, int $column, string $cellFormat) : string
+ {
+ $cell = $row[$column] ?? '';
+ $width = $this->effectiveColumnWidths[$column];
+ if ($cell instanceof TableCell && $cell->getColspan() > 1) {
+ // add the width of the following columns(numbers of colspan).
+ foreach (\range($column + 1, $column + $cell->getColspan() - 1) as $nextColumn) {
+ $width += $this->getColumnSeparatorWidth() + $this->effectiveColumnWidths[$nextColumn];
+ }
+ }
+ // str_pad won't work properly with multi-byte strings, we need to fix the padding
+ if (\false !== ($encoding = \mb_detect_encoding($cell, null, \true))) {
+ $width += \strlen($cell) - \mb_strwidth($cell, $encoding);
+ }
+ $style = $this->getColumnStyle($column);
+ if ($cell instanceof TableSeparator) {
+ return \sprintf($style->getBorderFormat(), \str_repeat($style->getBorderChars()[2], $width));
+ }
+ $width += Helper::length($cell) - Helper::length(Helper::removeDecoration($this->output->getFormatter(), $cell));
+ $content = \sprintf($style->getCellRowContentFormat(), $cell);
+ $padType = $style->getPadType();
+ if ($cell instanceof TableCell && $cell->getStyle() instanceof TableCellStyle) {
+ $isNotStyledByTag = !\preg_match('/^<(\\w+|(\\w+=[\\w,]+;?)*)>.+<\\/(\\w+|(\\w+=\\w+;?)*)?>$/', $cell);
+ if ($isNotStyledByTag) {
+ $cellFormat = $cell->getStyle()->getCellFormat();
+ if (!\is_string($cellFormat)) {
+ $tag = \http_build_query($cell->getStyle()->getTagOptions(), '', ';');
+ $cellFormat = '<' . $tag . '>%s>';
+ }
+ if (\strpos($content, '>') !== \false) {
+ $content = \str_replace('>', '', $content);
+ $width -= 3;
+ }
+ if (\strpos($content, '') !== \false) {
+ $content = \str_replace('', '', $content);
+ $width -= \strlen('');
+ }
+ }
+ $padType = $cell->getStyle()->getPadByAlign();
+ }
+ return \sprintf($cellFormat, \str_pad($content, $width, $style->getPaddingChar(), $padType));
+ }
+ /**
+ * Calculate number of columns for this table.
+ */
+ private function calculateNumberOfColumns(array $rows) : void
+ {
+ $columns = [0];
+ foreach ($rows as $row) {
+ if ($row instanceof TableSeparator) {
+ continue;
+ }
+ $columns[] = $this->getNumberOfColumns($row);
+ }
+ $this->numberOfColumns = \max($columns);
+ }
+ private function buildTableRows(array $rows) : TableRows
+ {
+ /** @var WrappableOutputFormatterInterface $formatter */
+ $formatter = $this->output->getFormatter();
+ $unmergedRows = [];
+ for ($rowKey = 0; $rowKey < \count($rows); ++$rowKey) {
+ $rows = $this->fillNextRows($rows, $rowKey);
+ // Remove any new line breaks and replace it with a new line
+ foreach ($rows[$rowKey] as $column => $cell) {
+ $colspan = $cell instanceof TableCell ? $cell->getColspan() : 1;
+ if (isset($this->columnMaxWidths[$column]) && Helper::width(Helper::removeDecoration($formatter, $cell)) > $this->columnMaxWidths[$column]) {
+ $cell = $formatter->formatAndWrap($cell, $this->columnMaxWidths[$column] * $colspan);
+ }
+ if (\strpos($cell ?? '', "\n") === \false) {
+ continue;
+ }
+ $escaped = \implode("\n", \array_map(\Closure::fromCallable([OutputFormatter::class, 'escapeTrailingBackslash']), \explode("\n", $cell)));
+ $cell = $cell instanceof TableCell ? new TableCell($escaped, ['colspan' => $cell->getColspan()]) : $escaped;
+ $lines = \explode("\n", \str_replace("\n", ">\n", $cell));
+ foreach ($lines as $lineKey => $line) {
+ if ($colspan > 1) {
+ $line = new TableCell($line, ['colspan' => $colspan]);
+ }
+ if (0 === $lineKey) {
+ $rows[$rowKey][$column] = $line;
+ } else {
+ if (!\array_key_exists($rowKey, $unmergedRows) || !\array_key_exists($lineKey, $unmergedRows[$rowKey])) {
+ $unmergedRows[$rowKey][$lineKey] = $this->copyRow($rows, $rowKey);
+ }
+ $unmergedRows[$rowKey][$lineKey][$column] = $line;
+ }
+ }
+ }
+ }
+ return new TableRows(function () use($rows, $unmergedRows) : \Traversable {
+ foreach ($rows as $rowKey => $row) {
+ $rowGroup = [$row instanceof TableSeparator ? $row : $this->fillCells($row)];
+ if (isset($unmergedRows[$rowKey])) {
+ foreach ($unmergedRows[$rowKey] as $row) {
+ $rowGroup[] = $row instanceof TableSeparator ? $row : $this->fillCells($row);
+ }
+ }
+ (yield $rowGroup);
+ }
+ });
+ }
+ private function calculateRowCount() : int
+ {
+ $numberOfRows = \count(\iterator_to_array($this->buildTableRows(\array_merge($this->headers, [new TableSeparator()], $this->rows))));
+ if ($this->headers) {
+ ++$numberOfRows;
+ // Add row for header separator
+ }
+ if ($this->rows) {
+ ++$numberOfRows;
+ // Add row for footer separator
+ }
+ return $numberOfRows;
+ }
+ /**
+ * fill rows that contains rowspan > 1.
+ *
+ * @throws InvalidArgumentException
+ */
+ private function fillNextRows(array $rows, int $line) : array
+ {
+ $unmergedRows = [];
+ foreach ($rows[$line] as $column => $cell) {
+ if (null !== $cell && !$cell instanceof TableCell && !\is_scalar($cell) && !$cell instanceof \Stringable) {
+ throw new InvalidArgumentException(\sprintf('A cell must be a TableCell, a scalar or an object implementing "__toString()", "%s" given.', \get_debug_type($cell)));
+ }
+ if ($cell instanceof TableCell && $cell->getRowspan() > 1) {
+ $nbLines = $cell->getRowspan() - 1;
+ $lines = [$cell];
+ if (\strpos($cell, "\n") !== \false) {
+ $lines = \explode("\n", \str_replace("\n", "\n>", $cell));
+ $nbLines = \count($lines) > $nbLines ? \substr_count($cell, "\n") : $nbLines;
+ $rows[$line][$column] = new TableCell($lines[0], ['colspan' => $cell->getColspan(), 'style' => $cell->getStyle()]);
+ unset($lines[0]);
+ }
+ // create a two dimensional array (rowspan x colspan)
+ $unmergedRows = \array_replace_recursive(\array_fill($line + 1, $nbLines, []), $unmergedRows);
+ foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
+ $value = $lines[$unmergedRowKey - $line] ?? '';
+ $unmergedRows[$unmergedRowKey][$column] = new TableCell($value, ['colspan' => $cell->getColspan(), 'style' => $cell->getStyle()]);
+ if ($nbLines === $unmergedRowKey - $line) {
+ break;
+ }
+ }
+ }
+ }
+ foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
+ // we need to know if $unmergedRow will be merged or inserted into $rows
+ if (isset($rows[$unmergedRowKey]) && \is_array($rows[$unmergedRowKey]) && $this->getNumberOfColumns($rows[$unmergedRowKey]) + $this->getNumberOfColumns($unmergedRows[$unmergedRowKey]) <= $this->numberOfColumns) {
+ foreach ($unmergedRow as $cellKey => $cell) {
+ // insert cell into row at cellKey position
+ \array_splice($rows[$unmergedRowKey], $cellKey, 0, [$cell]);
+ }
+ } else {
+ $row = $this->copyRow($rows, $unmergedRowKey - 1);
+ foreach ($unmergedRow as $column => $cell) {
+ if (!empty($cell)) {
+ $row[$column] = $unmergedRow[$column];
+ }
+ }
+ \array_splice($rows, $unmergedRowKey, 0, [$row]);
+ }
+ }
+ return $rows;
+ }
+ /**
+ * fill cells for a row that contains colspan > 1.
+ */
+ private function fillCells(iterable $row) : iterable
+ {
+ $newRow = [];
+ foreach ($row as $column => $cell) {
+ $newRow[] = $cell;
+ if ($cell instanceof TableCell && $cell->getColspan() > 1) {
+ foreach (\range($column + 1, $column + $cell->getColspan() - 1) as $position) {
+ // insert empty value at column position
+ $newRow[] = '';
+ }
+ }
+ }
+ return $newRow ?: $row;
+ }
+ private function copyRow(array $rows, int $line) : array
+ {
+ $row = $rows[$line];
+ foreach ($row as $cellKey => $cellValue) {
+ $row[$cellKey] = '';
+ if ($cellValue instanceof TableCell) {
+ $row[$cellKey] = new TableCell('', ['colspan' => $cellValue->getColspan()]);
+ }
+ }
+ return $row;
+ }
+ /**
+ * Gets number of columns by row.
+ */
+ private function getNumberOfColumns(array $row) : int
+ {
+ $columns = \count($row);
+ foreach ($row as $column) {
+ $columns += $column instanceof TableCell ? $column->getColspan() - 1 : 0;
+ }
+ return $columns;
+ }
+ /**
+ * Gets list of columns for the given row.
+ */
+ private function getRowColumns(array $row) : array
+ {
+ $columns = \range(0, $this->numberOfColumns - 1);
+ foreach ($row as $cellKey => $cell) {
+ if ($cell instanceof TableCell && $cell->getColspan() > 1) {
+ // exclude grouped columns.
+ $columns = \array_diff($columns, \range($cellKey + 1, $cellKey + $cell->getColspan() - 1));
+ }
+ }
+ return $columns;
+ }
+ /**
+ * Calculates columns widths.
+ */
+ private function calculateColumnsWidth(iterable $groups) : void
+ {
+ for ($column = 0; $column < $this->numberOfColumns; ++$column) {
+ $lengths = [];
+ foreach ($groups as $group) {
+ foreach ($group as $row) {
+ if ($row instanceof TableSeparator) {
+ continue;
+ }
+ foreach ($row as $i => $cell) {
+ if ($cell instanceof TableCell) {
+ $textContent = Helper::removeDecoration($this->output->getFormatter(), $cell);
+ $textLength = Helper::width($textContent);
+ if ($textLength > 0) {
+ $contentColumns = \mb_str_split($textContent, \ceil($textLength / $cell->getColspan()));
+ foreach ($contentColumns as $position => $content) {
+ $row[$i + $position] = $content;
+ }
+ }
+ }
+ }
+ $lengths[] = $this->getCellWidth($row, $column);
+ }
+ }
+ $this->effectiveColumnWidths[$column] = \max($lengths) + Helper::width($this->style->getCellRowContentFormat()) - 2;
+ }
+ }
+ private function getColumnSeparatorWidth() : int
+ {
+ return Helper::width(\sprintf($this->style->getBorderFormat(), $this->style->getBorderChars()[3]));
+ }
+ private function getCellWidth(array $row, int $column) : int
+ {
+ $cellWidth = 0;
+ if (isset($row[$column])) {
+ $cell = $row[$column];
+ $cellWidth = Helper::width(Helper::removeDecoration($this->output->getFormatter(), $cell));
+ }
+ $columnWidth = $this->columnWidths[$column] ?? 0;
+ $cellWidth = \max($cellWidth, $columnWidth);
+ return isset($this->columnMaxWidths[$column]) ? \min($this->columnMaxWidths[$column], $cellWidth) : $cellWidth;
+ }
+ /**
+ * Called after rendering to cleanup cache data.
+ */
+ private function cleanup() : void
+ {
+ $this->effectiveColumnWidths = [];
+ unset($this->numberOfColumns);
+ }
+ /**
+ * @return array
+ */
+ private static function initStyles() : array
+ {
+ $borderless = new TableStyle();
+ $borderless->setHorizontalBorderChars('=')->setVerticalBorderChars(' ')->setDefaultCrossingChar(' ');
+ $compact = new TableStyle();
+ $compact->setHorizontalBorderChars('')->setVerticalBorderChars('')->setDefaultCrossingChar('')->setCellRowContentFormat('%s ');
+ $styleGuide = new TableStyle();
+ $styleGuide->setHorizontalBorderChars('-')->setVerticalBorderChars(' ')->setDefaultCrossingChar(' ')->setCellHeaderFormat('%s');
+ $box = (new TableStyle())->setHorizontalBorderChars('─')->setVerticalBorderChars('│')->setCrossingChars('┼', '┌', '┬', '┐', '┤', '┘', '┴', '└', '├');
+ $boxDouble = (new TableStyle())->setHorizontalBorderChars('═', '─')->setVerticalBorderChars('║', '│')->setCrossingChars('┼', '╔', '╤', '╗', '╢', '╝', '╧', '╚', '╟', '╠', '╪', '╣');
+ return ['default' => new TableStyle(), 'borderless' => $borderless, 'compact' => $compact, 'symfony-style-guide' => $styleGuide, 'box' => $box, 'box-double' => $boxDouble];
+ }
+ /**
+ * @param \Symfony\Component\Console\Helper\TableStyle|string $name
+ */
+ private function resolveStyle($name) : TableStyle
+ {
+ if ($name instanceof TableStyle) {
+ return $name;
+ }
+ if (!isset(self::$styles[$name])) {
+ throw new InvalidArgumentException(\sprintf('Style "%s" is not defined.', $name));
+ }
+ return self::$styles[$name];
+ }
+}
diff --git a/vendor/symfony/console/Helper/TableCell.php b/vendor/symfony/console/Helper/TableCell.php
new file mode 100644
index 00000000..2b786cdb
--- /dev/null
+++ b/vendor/symfony/console/Helper/TableCell.php
@@ -0,0 +1,64 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Helper;
+
+use ClassLeak202307\Symfony\Component\Console\Exception\InvalidArgumentException;
+/**
+ * @author Abdellatif Ait boudad
+ */
+class TableCell
+{
+ /**
+ * @var string
+ */
+ private $value;
+ /**
+ * @var mixed[]
+ */
+ private $options = ['rowspan' => 1, 'colspan' => 1, 'style' => null];
+ public function __construct(string $value = '', array $options = [])
+ {
+ $this->value = $value;
+ // check option names
+ if ($diff = \array_diff(\array_keys($options), \array_keys($this->options))) {
+ 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.
+ */
+ public function __toString() : string
+ {
+ return $this->value;
+ }
+ /**
+ * Gets number of colspan.
+ */
+ public function getColspan() : int
+ {
+ return (int) $this->options['colspan'];
+ }
+ /**
+ * Gets number of rowspan.
+ */
+ public function getRowspan() : int
+ {
+ return (int) $this->options['rowspan'];
+ }
+ public function getStyle() : ?TableCellStyle
+ {
+ return $this->options['style'];
+ }
+}
diff --git a/vendor/symfony/console/Helper/TableCellStyle.php b/vendor/symfony/console/Helper/TableCellStyle.php
new file mode 100644
index 00000000..20f0ea93
--- /dev/null
+++ b/vendor/symfony/console/Helper/TableCellStyle.php
@@ -0,0 +1,59 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Helper;
+
+use ClassLeak202307\Symfony\Component\Console\Exception\InvalidArgumentException;
+/**
+ * @author Yewhen Khoptynskyi
+ */
+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];
+ /**
+ * @var mixed[]
+ */
+ private $options = ['fg' => 'default', 'bg' => 'default', 'options' => null, 'align' => self::DEFAULT_ALIGN, 'cellFormat' => null];
+ public function __construct(array $options = [])
+ {
+ if ($diff = \array_diff(\array_keys($options), \array_keys($this->options))) {
+ throw new InvalidArgumentException(\sprintf('The TableCellStyle does not support the following options: \'%s\'.', \implode('\', \'', $diff)));
+ }
+ if (isset($options['align']) && !\array_key_exists($options['align'], self::ALIGN_MAP)) {
+ throw new InvalidArgumentException(\sprintf('Wrong align value. Value must be following: \'%s\'.', \implode('\', \'', \array_keys(self::ALIGN_MAP))));
+ }
+ $this->options = \array_merge($this->options, $options);
+ }
+ public function getOptions() : array
+ {
+ return $this->options;
+ }
+ /**
+ * Gets options we need for tag for example fg, bg.
+ *
+ * @return string[]
+ */
+ public function getTagOptions() : 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'];
+ }
+}
diff --git a/vendor/symfony/console/Helper/TableRows.php b/vendor/symfony/console/Helper/TableRows.php
new file mode 100644
index 00000000..2d4ea3a8
--- /dev/null
+++ b/vendor/symfony/console/Helper/TableRows.php
@@ -0,0 +1,30 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Helper;
+
+/**
+ * @internal
+ */
+class TableRows implements \IteratorAggregate
+{
+ /**
+ * @var \Closure
+ */
+ private $generator;
+ public function __construct(\Closure $generator)
+ {
+ $this->generator = $generator;
+ }
+ public function getIterator() : \Traversable
+ {
+ return ($this->generator)();
+ }
+}
diff --git a/vendor/symfony/console/Helper/TableSeparator.php b/vendor/symfony/console/Helper/TableSeparator.php
new file mode 100644
index 00000000..1384aea6
--- /dev/null
+++ b/vendor/symfony/console/Helper/TableSeparator.php
@@ -0,0 +1,24 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Helper;
+
+/**
+ * Marks a row as being a separator.
+ *
+ * @author Fabien Potencier
+ */
+class TableSeparator extends TableCell
+{
+ public function __construct(array $options = [])
+ {
+ parent::__construct('', $options);
+ }
+}
diff --git a/vendor/symfony/console/Helper/TableStyle.php b/vendor/symfony/console/Helper/TableStyle.php
new file mode 100644
index 00000000..0c04196c
--- /dev/null
+++ b/vendor/symfony/console/Helper/TableStyle.php
@@ -0,0 +1,378 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Helper;
+
+use ClassLeak202307\Symfony\Component\Console\Exception\InvalidArgumentException;
+use ClassLeak202307\Symfony\Component\Console\Exception\LogicException;
+/**
+ * Defines the styles for a Table.
+ *
+ * @author Fabien Potencier
+ * @author Саша Стаменковић
+ * @author Dany Maillard
+ */
+class TableStyle
+{
+ /**
+ * @var string
+ */
+ private $paddingChar = ' ';
+ /**
+ * @var string
+ */
+ private $horizontalOutsideBorderChar = '-';
+ /**
+ * @var string
+ */
+ private $horizontalInsideBorderChar = '-';
+ /**
+ * @var string
+ */
+ private $verticalOutsideBorderChar = '|';
+ /**
+ * @var string
+ */
+ private $verticalInsideBorderChar = '|';
+ /**
+ * @var string
+ */
+ private $crossingChar = '+';
+ /**
+ * @var string
+ */
+ private $crossingTopRightChar = '+';
+ /**
+ * @var string
+ */
+ private $crossingTopMidChar = '+';
+ /**
+ * @var string
+ */
+ private $crossingTopLeftChar = '+';
+ /**
+ * @var string
+ */
+ private $crossingMidRightChar = '+';
+ /**
+ * @var string
+ */
+ private $crossingBottomRightChar = '+';
+ /**
+ * @var string
+ */
+ private $crossingBottomMidChar = '+';
+ /**
+ * @var string
+ */
+ private $crossingBottomLeftChar = '+';
+ /**
+ * @var string
+ */
+ private $crossingMidLeftChar = '+';
+ /**
+ * @var string
+ */
+ private $crossingTopLeftBottomChar = '+';
+ /**
+ * @var string
+ */
+ private $crossingTopMidBottomChar = '+';
+ /**
+ * @var string
+ */
+ private $crossingTopRightBottomChar = '+';
+ /**
+ * @var string
+ */
+ private $headerTitleFormat = ' %s >';
+ /**
+ * @var string
+ */
+ private $footerTitleFormat = ' %s >';
+ /**
+ * @var string
+ */
+ private $cellHeaderFormat = '%s';
+ /**
+ * @var string
+ */
+ private $cellRowFormat = '%s';
+ /**
+ * @var string
+ */
+ private $cellRowContentFormat = ' %s ';
+ /**
+ * @var string
+ */
+ private $borderFormat = '%s';
+ /**
+ * @var int
+ */
+ private $padType = \STR_PAD_RIGHT;
+ /**
+ * Sets padding character, used for cell padding.
+ *
+ * @return $this
+ */
+ public function setPaddingChar(string $paddingChar)
+ {
+ if (!$paddingChar) {
+ throw new LogicException('The padding char must not be empty.');
+ }
+ $this->paddingChar = $paddingChar;
+ return $this;
+ }
+ /**
+ * Gets padding character, used for cell padding.
+ */
+ public function getPaddingChar() : string
+ {
+ return $this->paddingChar;
+ }
+ /**
+ * Sets horizontal border characters.
+ *
+ *
+ * ╔═══════════════╤══════════════════════════╤══════════════════╗
+ * 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 ║
+ * ╚═══════════════╧══════════════════════════╧══════════════════╝
+ *
+ *
+ * @return $this
+ */
+ public function setHorizontalBorderChars(string $outside, string $inside = null)
+ {
+ $this->horizontalOutsideBorderChar = $outside;
+ $this->horizontalInsideBorderChar = $inside ?? $outside;
+ return $this;
+ }
+ /**
+ * Sets vertical border characters.
+ *
+ *
+ * ╔═══════════════╤══════════════════════════╤══════════════════╗
+ * ║ 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 ║
+ * ╚═══════════════╧══════════════════════════╧══════════════════╝
+ *
+ *
+ * @return $this
+ */
+ public function setVerticalBorderChars(string $outside, string $inside = null)
+ {
+ $this->verticalOutsideBorderChar = $outside;
+ $this->verticalInsideBorderChar = $inside ?? $outside;
+ return $this;
+ }
+ /**
+ * Gets border characters.
+ *
+ * @internal
+ */
+ public function getBorderChars() : array
+ {
+ return [$this->horizontalOutsideBorderChar, $this->verticalOutsideBorderChar, $this->horizontalInsideBorderChar, $this->verticalInsideBorderChar];
+ }
+ /**
+ * Sets crossing characters.
+ *
+ * Example:
+ *
+ * 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
+ *
+ *
+ * @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 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)
+ {
+ $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.
+ */
+ public function getCrossingChar() : string
+ {
+ return $this->crossingChar;
+ }
+ /**
+ * Gets crossing characters.
+ *
+ * @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(string $cellHeaderFormat)
+ {
+ $this->cellHeaderFormat = $cellHeaderFormat;
+ return $this;
+ }
+ /**
+ * Gets header cell format.
+ */
+ public function getCellHeaderFormat() : string
+ {
+ return $this->cellHeaderFormat;
+ }
+ /**
+ * Sets row cell format.
+ *
+ * @return $this
+ */
+ public function setCellRowFormat(string $cellRowFormat)
+ {
+ $this->cellRowFormat = $cellRowFormat;
+ return $this;
+ }
+ /**
+ * Gets row cell format.
+ */
+ public function getCellRowFormat() : string
+ {
+ return $this->cellRowFormat;
+ }
+ /**
+ * Sets row cell content format.
+ *
+ * @return $this
+ */
+ public function setCellRowContentFormat(string $cellRowContentFormat)
+ {
+ $this->cellRowContentFormat = $cellRowContentFormat;
+ return $this;
+ }
+ /**
+ * Gets row cell content format.
+ */
+ public function getCellRowContentFormat() : string
+ {
+ return $this->cellRowContentFormat;
+ }
+ /**
+ * Sets table border format.
+ *
+ * @return $this
+ */
+ public function setBorderFormat(string $borderFormat)
+ {
+ $this->borderFormat = $borderFormat;
+ return $this;
+ }
+ /**
+ * Gets table border format.
+ */
+ public function getBorderFormat() : string
+ {
+ return $this->borderFormat;
+ }
+ /**
+ * Sets cell padding type.
+ *
+ * @return $this
+ */
+ public function setPadType(int $padType)
+ {
+ if (!\in_array($padType, [\STR_PAD_LEFT, \STR_PAD_RIGHT, \STR_PAD_BOTH], \true)) {
+ throw new InvalidArgumentException('Invalid padding type. Expected one of (STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH).');
+ }
+ $this->padType = $padType;
+ return $this;
+ }
+ /**
+ * Gets cell padding type.
+ */
+ public function getPadType() : int
+ {
+ return $this->padType;
+ }
+ public function getHeaderTitleFormat() : string
+ {
+ return $this->headerTitleFormat;
+ }
+ /**
+ * @return $this
+ */
+ public function setHeaderTitleFormat(string $format)
+ {
+ $this->headerTitleFormat = $format;
+ return $this;
+ }
+ public function getFooterTitleFormat() : string
+ {
+ return $this->footerTitleFormat;
+ }
+ /**
+ * @return $this
+ */
+ public function setFooterTitleFormat(string $format)
+ {
+ $this->footerTitleFormat = $format;
+ return $this;
+ }
+}
diff --git a/vendor/symfony/console/Input/ArgvInput.php b/vendor/symfony/console/Input/ArgvInput.php
new file mode 100644
index 00000000..1f2b3e0f
--- /dev/null
+++ b/vendor/symfony/console/Input/ArgvInput.php
@@ -0,0 +1,336 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Input;
+
+use ClassLeak202307\Symfony\Component\Console\Exception\RuntimeException;
+/**
+ * ArgvInput represents an input coming from the CLI arguments.
+ *
+ * Usage:
+ *
+ * $input = new ArgvInput();
+ *
+ * By default, the `$_SERVER['argv']` array is used for the input values.
+ *
+ * This can be overridden by explicitly passing the input values in the constructor:
+ *
+ * $input = new ArgvInput($_SERVER['argv']);
+ *
+ * If you pass it yourself, don't forget that the first element of the array
+ * is the name of the running application.
+ *
+ * When passing an argument to the constructor, be sure that it respects
+ * the same rules as the argv one. It's almost always better to use the
+ * `StringInput` when you want to provide your own input.
+ *
+ * @author Fabien Potencier
+ *
+ * @see http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html
+ * @see http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html#tag_12_02
+ */
+class ArgvInput extends Input
+{
+ /**
+ * @var mixed[]
+ */
+ private $tokens;
+ /**
+ * @var mixed[]
+ */
+ private $parsed;
+ public function __construct(array $argv = null, InputDefinition $definition = null)
+ {
+ $argv = $argv ?? $_SERVER['argv'] ?? [];
+ // strip the application name
+ \array_shift($argv);
+ $this->tokens = $argv;
+ parent::__construct($definition);
+ }
+ /**
+ * @return void
+ */
+ protected function setTokens(array $tokens)
+ {
+ $this->tokens = $tokens;
+ }
+ /**
+ * @return void
+ */
+ protected function parse()
+ {
+ $parseOptions = \true;
+ $this->parsed = $this->tokens;
+ while (null !== ($token = \array_shift($this->parsed))) {
+ $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 && \strncmp($token, '--', \strlen('--')) === 0) {
+ $this->parseLongOption($token);
+ } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) {
+ $this->parseShortOption($token);
+ } else {
+ $this->parseArgument($token);
+ }
+ return $parseOptions;
+ }
+ /**
+ * Parses a short option.
+ */
+ private function parseShortOption(string $token) : void
+ {
+ $name = \substr($token, 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));
+ } else {
+ $this->parseShortOptionSet($name);
+ }
+ } else {
+ $this->addShortOption($name, null);
+ }
+ }
+ /**
+ * Parses a short option set.
+ *
+ * @throws RuntimeException When option given doesn't exist
+ */
+ private function parseShortOptionSet(string $name) : void
+ {
+ $len = \strlen($name);
+ for ($i = 0; $i < $len; ++$i) {
+ if (!$this->definition->hasShortcut($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]);
+ if ($option->acceptValue()) {
+ $this->addLongOption($option->getName(), $i === $len - 1 ? null : \substr($name, $i + 1));
+ break;
+ } else {
+ $this->addLongOption($option->getName(), null);
+ }
+ }
+ }
+ /**
+ * Parses a long option.
+ */
+ private function parseLongOption(string $token) : void
+ {
+ $name = \substr($token, 2);
+ if (\false !== ($pos = \strpos($name, '='))) {
+ if ('' === ($value = \substr($name, $pos + 1))) {
+ \array_unshift($this->parsed, $value);
+ }
+ $this->addLongOption(\substr($name, 0, $pos), $value);
+ } else {
+ $this->addLongOption($name, null);
+ }
+ }
+ /**
+ * Parses an argument.
+ *
+ * @throws RuntimeException When too many arguments are given
+ */
+ private function parseArgument(string $token) : void
+ {
+ $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() ? [$token] : $token;
+ // if last argument isArray(), append token to last argument
+ } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) {
+ $arg = $this->definition->getArgument($c - 1);
+ $this->arguments[$arg->getName()][] = $token;
+ // unexpected argument
+ } else {
+ $all = $this->definition->getArguments();
+ $symfonyCommandName = null;
+ \reset($all);
+ if (($inputArgument = $all[$key = \key($all)] ?? null) && 'command' === $inputArgument->getName()) {
+ $symfonyCommandName = $this->arguments['command'] ?? null;
+ unset($all[$key]);
+ }
+ 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.
+ *
+ * @throws RuntimeException When option given doesn't exist
+ * @param mixed $value
+ */
+ private function addShortOption(string $shortcut, $value) : void
+ {
+ if (!$this->definition->hasShortcut($shortcut)) {
+ throw new RuntimeException(\sprintf('The "-%s" option does not exist.', $shortcut));
+ }
+ $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
+ }
+ /**
+ * Adds a long option value.
+ *
+ * @throws RuntimeException When option given doesn't exist
+ * @param mixed $value
+ */
+ private function addLongOption(string $name, $value) : void
+ {
+ if (!$this->definition->hasOption($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);
+ if (null !== $value && !$option->acceptValue()) {
+ throw new RuntimeException(\sprintf('The "--%s" option does not accept a value.', $name));
+ }
+ 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, ['', null], \true)) {
+ $value = $next;
+ } else {
+ \array_unshift($this->parsed, $next);
+ }
+ }
+ if (null === $value) {
+ if ($option->isValueRequired()) {
+ throw new RuntimeException(\sprintf('The "--%s" option requires a value.', $name));
+ }
+ if (!$option->isArray() && !$option->isValueOptional()) {
+ $value = \true;
+ }
+ }
+ if ($option->isArray()) {
+ $this->options[$name][] = $value;
+ } else {
+ $this->options[$name] = $value;
+ }
+ }
+ public function getFirstArgument() : ?string
+ {
+ $isOption = \false;
+ foreach ($this->tokens as $i => $token) {
+ if ($token && '-' === $token[0]) {
+ if (\strpos($token, '=') !== \false || !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;
+ }
+ /**
+ * @param string|mixed[] $values
+ */
+ public function hasParameterOption($values, bool $onlyParams = \false) : bool
+ {
+ $values = (array) $values;
+ foreach ($this->tokens as $token) {
+ if ($onlyParams && '--' === $token) {
+ return \false;
+ }
+ foreach ($values as $value) {
+ // Options with values:
+ // For long options, test for '--option=' at beginning
+ // For short options, test for '-o' at beginning
+ $leading = \strncmp($value, '--', \strlen('--')) === 0 ? $value . '=' : $value;
+ if ($token === $value || '' !== $leading && \strncmp($token, $leading, \strlen($leading)) === 0) {
+ return \true;
+ }
+ }
+ }
+ return \false;
+ }
+ /**
+ * @param string|mixed[] $values
+ * @param string|bool|int|float|mixed[]|null $default
+ * @return mixed
+ */
+ public function getParameterOption($values, $default = \false, bool $onlyParams = \false)
+ {
+ $values = (array) $values;
+ $tokens = $this->tokens;
+ while (0 < \count($tokens)) {
+ $token = \array_shift($tokens);
+ if ($onlyParams && '--' === $token) {
+ return $default;
+ }
+ foreach ($values as $value) {
+ 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 = \strncmp($value, '--', \strlen('--')) === 0 ? $value . '=' : $value;
+ if ('' !== $leading && \strncmp($token, $leading, \strlen($leading)) === 0) {
+ return \substr($token, \strlen($leading));
+ }
+ }
+ }
+ return $default;
+ }
+ /**
+ * Returns a stringified representation of the args passed to the command.
+ */
+ 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]) {
+ return $this->escapeToken($token);
+ }
+ return $token;
+ }, $this->tokens);
+ return \implode(' ', $tokens);
+ }
+}
diff --git a/vendor/symfony/console/Input/ArrayInput.php b/vendor/symfony/console/Input/ArrayInput.php
new file mode 100644
index 00000000..760e35fb
--- /dev/null
+++ b/vendor/symfony/console/Input/ArrayInput.php
@@ -0,0 +1,181 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Input;
+
+use ClassLeak202307\Symfony\Component\Console\Exception\InvalidArgumentException;
+use ClassLeak202307\Symfony\Component\Console\Exception\InvalidOptionException;
+/**
+ * ArrayInput represents an input provided as an array.
+ *
+ * Usage:
+ *
+ * $input = new ArrayInput(['command' => 'foo:bar', 'foo' => 'bar', '--bar' => 'foobar']);
+ *
+ * @author Fabien Potencier
+ */
+class ArrayInput extends Input
+{
+ /**
+ * @var mixed[]
+ */
+ private $parameters;
+ public function __construct(array $parameters, InputDefinition $definition = null)
+ {
+ $this->parameters = $parameters;
+ parent::__construct($definition);
+ }
+ public function getFirstArgument() : ?string
+ {
+ foreach ($this->parameters as $param => $value) {
+ if ($param && \is_string($param) && '-' === $param[0]) {
+ continue;
+ }
+ return $value;
+ }
+ return null;
+ }
+ /**
+ * @param string|mixed[] $values
+ */
+ public function hasParameterOption($values, bool $onlyParams = \false) : bool
+ {
+ $values = (array) $values;
+ foreach ($this->parameters as $k => $v) {
+ if (!\is_int($k)) {
+ $v = $k;
+ }
+ if ($onlyParams && '--' === $v) {
+ return \false;
+ }
+ if (\in_array($v, $values)) {
+ return \true;
+ }
+ }
+ return \false;
+ }
+ /**
+ * @param string|mixed[] $values
+ * @param string|bool|int|float|mixed[]|null $default
+ * @return mixed
+ */
+ public function getParameterOption($values, $default = \false, bool $onlyParams = \false)
+ {
+ $values = (array) $values;
+ foreach ($this->parameters as $k => $v) {
+ if ($onlyParams && ('--' === $k || \is_int($k) && '--' === $v)) {
+ return $default;
+ }
+ if (\is_int($k)) {
+ if (\in_array($v, $values)) {
+ return \true;
+ }
+ } elseif (\in_array($k, $values)) {
+ return $v;
+ }
+ }
+ return $default;
+ }
+ /**
+ * Returns a stringified representation of the args passed to the command.
+ */
+ public function __toString() : string
+ {
+ $params = [];
+ foreach ($this->parameters as $param => $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[] = \is_array($val) ? \implode(' ', \array_map(\Closure::fromCallable([$this, 'escapeToken']), $val)) : $this->escapeToken($val);
+ }
+ }
+ return \implode(' ', $params);
+ }
+ /**
+ * @return void
+ */
+ protected function parse()
+ {
+ foreach ($this->parameters as $key => $value) {
+ if ('--' === $key) {
+ return;
+ }
+ if (\strncmp($key, '--', \strlen('--')) === 0) {
+ $this->addLongOption(\substr($key, 2), $value);
+ } elseif (\strncmp($key, '-', \strlen('-')) === 0) {
+ $this->addShortOption(\substr($key, 1), $value);
+ } else {
+ $this->addArgument($key, $value);
+ }
+ }
+ }
+ /**
+ * Adds a short option value.
+ *
+ * @throws InvalidOptionException When option given doesn't exist
+ * @param mixed $value
+ */
+ private function addShortOption(string $shortcut, $value) : void
+ {
+ if (!$this->definition->hasShortcut($shortcut)) {
+ throw new InvalidOptionException(\sprintf('The "-%s" option does not exist.', $shortcut));
+ }
+ $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
+ }
+ /**
+ * Adds a long option value.
+ *
+ * @throws InvalidOptionException When option given doesn't exist
+ * @throws InvalidOptionException When a required value is missing
+ * @param mixed $value
+ */
+ private function addLongOption(string $name, $value) : void
+ {
+ if (!$this->definition->hasOption($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);
+ if (null === $value) {
+ if ($option->isValueRequired()) {
+ throw new InvalidOptionException(\sprintf('The "--%s" option requires a value.', $name));
+ }
+ if (!$option->isValueOptional()) {
+ $value = \true;
+ }
+ }
+ $this->options[$name] = $value;
+ }
+ /**
+ * Adds an argument value.
+ *
+ * @throws InvalidArgumentException When argument given doesn't exist
+ * @param string|int $name
+ * @param mixed $value
+ */
+ private function addArgument($name, $value) : void
+ {
+ if (!$this->definition->hasArgument($name)) {
+ throw new InvalidArgumentException(\sprintf('The "%s" argument does not exist.', $name));
+ }
+ $this->arguments[$name] = $value;
+ }
+}
diff --git a/vendor/symfony/console/Input/Input.php b/vendor/symfony/console/Input/Input.php
new file mode 100644
index 00000000..58ff30df
--- /dev/null
+++ b/vendor/symfony/console/Input/Input.php
@@ -0,0 +1,173 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Input;
+
+use ClassLeak202307\Symfony\Component\Console\Exception\InvalidArgumentException;
+use ClassLeak202307\Symfony\Component\Console\Exception\RuntimeException;
+/**
+ * Input is the base class for all concrete Input classes.
+ *
+ * Three concrete classes are provided by default:
+ *
+ * * `ArgvInput`: The input comes from the CLI arguments (argv)
+ * * `StringInput`: The input is provided as a string
+ * * `ArrayInput`: The input is provided as an array
+ *
+ * @author Fabien Potencier
+ */
+abstract class Input implements InputInterface, StreamableInputInterface
+{
+ protected $definition;
+ protected $stream;
+ protected $options = [];
+ protected $arguments = [];
+ protected $interactive = \true;
+ public function __construct(InputDefinition $definition = null)
+ {
+ if (null === $definition) {
+ $this->definition = new InputDefinition();
+ } else {
+ $this->bind($definition);
+ $this->validate();
+ }
+ }
+ /**
+ * @return void
+ */
+ public function bind(InputDefinition $definition)
+ {
+ $this->arguments = [];
+ $this->options = [];
+ $this->definition = $definition;
+ $this->parse();
+ }
+ /**
+ * Processes command line arguments.
+ *
+ * @return void
+ */
+ protected abstract function parse();
+ /**
+ * @return void
+ */
+ public function validate()
+ {
+ $definition = $this->definition;
+ $givenArguments = $this->arguments;
+ $missingArguments = \array_filter(\array_keys($definition->getArguments()), function ($argument) use($givenArguments, $definition) {
+ return !\array_key_exists($argument, $givenArguments) && $definition->getArgument($argument)->isRequired();
+ });
+ if (\count($missingArguments) > 0) {
+ throw new RuntimeException(\sprintf('Not enough arguments (missing: "%s").', \implode(', ', $missingArguments)));
+ }
+ }
+ public function isInteractive() : bool
+ {
+ return $this->interactive;
+ }
+ /**
+ * @return void
+ */
+ public function setInteractive(bool $interactive)
+ {
+ $this->interactive = $interactive;
+ }
+ public function getArguments() : array
+ {
+ return \array_merge($this->definition->getArgumentDefaults(), $this->arguments);
+ }
+ /**
+ * @return mixed
+ */
+ public function getArgument(string $name)
+ {
+ if (!$this->definition->hasArgument($name)) {
+ throw new InvalidArgumentException(\sprintf('The "%s" argument does not exist.', $name));
+ }
+ return $this->arguments[$name] ?? $this->definition->getArgument($name)->getDefault();
+ }
+ /**
+ * @return void
+ * @param mixed $value
+ */
+ public function setArgument(string $name, $value)
+ {
+ if (!$this->definition->hasArgument($name)) {
+ throw new InvalidArgumentException(\sprintf('The "%s" argument does not exist.', $name));
+ }
+ $this->arguments[$name] = $value;
+ }
+ public function hasArgument(string $name) : bool
+ {
+ return $this->definition->hasArgument($name);
+ }
+ public function getOptions() : array
+ {
+ return \array_merge($this->definition->getOptionDefaults(), $this->options);
+ }
+ /**
+ * @return mixed
+ */
+ public function getOption(string $name)
+ {
+ 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 void
+ * @param mixed $value
+ */
+ public function setOption(string $name, $value)
+ {
+ 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));
+ }
+ $this->options[$name] = $value;
+ }
+ public function hasOption(string $name) : bool
+ {
+ return $this->definition->hasOption($name) || $this->definition->hasNegation($name);
+ }
+ /**
+ * Escapes a token through escapeshellarg if it contains unsafe chars.
+ */
+ public function escapeToken(string $token) : string
+ {
+ return \preg_match('{^[\\w-]+$}', $token) ? $token : \escapeshellarg($token);
+ }
+ /**
+ * @param resource $stream
+ *
+ * @return void
+ */
+ public function setStream($stream)
+ {
+ $this->stream = $stream;
+ }
+ /**
+ * @return resource
+ */
+ public function getStream()
+ {
+ return $this->stream;
+ }
+}
diff --git a/vendor/symfony/console/Input/InputArgument.php b/vendor/symfony/console/Input/InputArgument.php
new file mode 100644
index 00000000..97e4cf27
--- /dev/null
+++ b/vendor/symfony/console/Input/InputArgument.php
@@ -0,0 +1,155 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Input;
+
+use ClassLeak202307\Symfony\Component\Console\Command\Command;
+use ClassLeak202307\Symfony\Component\Console\Completion\CompletionInput;
+use ClassLeak202307\Symfony\Component\Console\Completion\CompletionSuggestions;
+use ClassLeak202307\Symfony\Component\Console\Completion\Suggestion;
+use ClassLeak202307\Symfony\Component\Console\Exception\InvalidArgumentException;
+use ClassLeak202307\Symfony\Component\Console\Exception\LogicException;
+/**
+ * Represents a command line argument.
+ *
+ * @author Fabien Potencier
+ */
+class InputArgument
+{
+ public const REQUIRED = 1;
+ public const OPTIONAL = 2;
+ public const IS_ARRAY = 4;
+ /**
+ * @var string
+ */
+ private $name;
+ /**
+ * @var int
+ */
+ private $mode;
+ /**
+ * @var string|int|bool|mixed[]|null|float
+ */
+ private $default;
+ /**
+ * @var mixed[]|\Closure
+ */
+ private $suggestedValues;
+ /**
+ * @var string
+ */
+ private $description;
+ /**
+ * @param string $name The argument name
+ * @param int|null $mode The argument mode: a bit mask of self::REQUIRED, self::OPTIONAL and self::IS_ARRAY
+ * @param string $description A description text
+ * @param string|bool|int|float|mixed[] $default The default value (for self::OPTIONAL mode only)
+ * @param array|\Closure(CompletionInput,CompletionSuggestions):list $suggestedValues The values used for input completion
+ *
+ * @throws InvalidArgumentException When argument mode is not valid
+ */
+ public function __construct(string $name, int $mode = null, string $description = '', $default = null, $suggestedValues = [])
+ {
+ if (null === $mode) {
+ $mode = self::OPTIONAL;
+ } elseif ($mode > 7 || $mode < 1) {
+ throw new InvalidArgumentException(\sprintf('Argument mode "%s" is not valid.', $mode));
+ }
+ $this->name = $name;
+ $this->mode = $mode;
+ $this->description = $description;
+ $this->suggestedValues = $suggestedValues;
+ $this->setDefault($default);
+ }
+ /**
+ * Returns the argument name.
+ */
+ public function getName() : string
+ {
+ return $this->name;
+ }
+ /**
+ * Returns true if the argument is required.
+ *
+ * @return bool true if parameter mode is self::REQUIRED, false otherwise
+ */
+ public function isRequired() : bool
+ {
+ return self::REQUIRED === (self::REQUIRED & $this->mode);
+ }
+ /**
+ * Returns true if the argument can take multiple values.
+ *
+ * @return bool true if mode is self::IS_ARRAY, false otherwise
+ */
+ public function isArray() : bool
+ {
+ return self::IS_ARRAY === (self::IS_ARRAY & $this->mode);
+ }
+ /**
+ * Sets the default value.
+ *
+ * @return void
+ *
+ * @throws LogicException When incorrect default value is given
+ * @param string|bool|int|float|mixed[] $default
+ */
+ public function setDefault($default = null)
+ {
+ if (1 > \func_num_args()) {
+ trigger_deprecation('symfony/console', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
+ }
+ 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 = [];
+ } elseif (!\is_array($default)) {
+ throw new LogicException('A default value for an array argument must be an array.');
+ }
+ }
+ $this->default = $default;
+ }
+ /**
+ * Returns the default value.
+ * @return string|bool|int|float|mixed[]|null
+ */
+ public function getDefault()
+ {
+ return $this->default;
+ }
+ public function hasCompletion() : bool
+ {
+ return [] !== $this->suggestedValues;
+ }
+ /**
+ * Adds suggestions to $suggestions for the current completion input.
+ *
+ * @see Command::complete()
+ */
+ public function complete(CompletionInput $input, CompletionSuggestions $suggestions) : void
+ {
+ $values = $this->suggestedValues;
+ if ($values instanceof \Closure && !\is_array($values = $values($input))) {
+ throw new LogicException(\sprintf('Closure for argument "%s" must return an array. Got "%s".', $this->name, \get_debug_type($values)));
+ }
+ if ($values) {
+ $suggestions->suggestValues($values);
+ }
+ }
+ /**
+ * Returns the description text.
+ */
+ public function getDescription() : string
+ {
+ return $this->description;
+ }
+}
diff --git a/vendor/symfony/console/Input/InputAwareInterface.php b/vendor/symfony/console/Input/InputAwareInterface.php
new file mode 100644
index 00000000..44826692
--- /dev/null
+++ b/vendor/symfony/console/Input/InputAwareInterface.php
@@ -0,0 +1,27 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Input;
+
+/**
+ * InputAwareInterface should be implemented by classes that depends on the
+ * Console Input.
+ *
+ * @author Wouter J
+ */
+interface InputAwareInterface
+{
+ /**
+ * Sets the Console Input.
+ *
+ * @return void
+ */
+ public function setInput(InputInterface $input);
+}
diff --git a/vendor/symfony/console/Input/InputDefinition.php b/vendor/symfony/console/Input/InputDefinition.php
new file mode 100644
index 00000000..9b98cc26
--- /dev/null
+++ b/vendor/symfony/console/Input/InputDefinition.php
@@ -0,0 +1,384 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Input;
+
+use ClassLeak202307\Symfony\Component\Console\Exception\InvalidArgumentException;
+use ClassLeak202307\Symfony\Component\Console\Exception\LogicException;
+/**
+ * A InputDefinition represents a set of valid command line arguments and options.
+ *
+ * Usage:
+ *
+ * $definition = new InputDefinition([
+ * new InputArgument('name', InputArgument::REQUIRED),
+ * new InputOption('foo', 'f', InputOption::VALUE_REQUIRED),
+ * ]);
+ *
+ * @author Fabien Potencier
+ */
+class InputDefinition
+{
+ /**
+ * @var mixed[]
+ */
+ private $arguments = [];
+ /**
+ * @var int
+ */
+ private $requiredCount = 0;
+ /**
+ * @var \Symfony\Component\Console\Input\InputArgument|null
+ */
+ private $lastArrayArgument;
+ /**
+ * @var \Symfony\Component\Console\Input\InputArgument|null
+ */
+ private $lastOptionalArgument;
+ /**
+ * @var mixed[]
+ */
+ private $options = [];
+ /**
+ * @var mixed[]
+ */
+ private $negations = [];
+ /**
+ * @var mixed[]
+ */
+ private $shortcuts = [];
+ /**
+ * @param array $definition An array of InputArgument and InputOption instance
+ */
+ public function __construct(array $definition = [])
+ {
+ $this->setDefinition($definition);
+ }
+ /**
+ * Sets the definition of the input.
+ *
+ * @return void
+ */
+ public function setDefinition(array $definition)
+ {
+ $arguments = [];
+ $options = [];
+ foreach ($definition as $item) {
+ if ($item instanceof InputOption) {
+ $options[] = $item;
+ } else {
+ $arguments[] = $item;
+ }
+ }
+ $this->setArguments($arguments);
+ $this->setOptions($options);
+ }
+ /**
+ * Sets the InputArgument objects.
+ *
+ * @param InputArgument[] $arguments An array of InputArgument objects
+ *
+ * @return void
+ */
+ public function setArguments(array $arguments = [])
+ {
+ $this->arguments = [];
+ $this->requiredCount = 0;
+ $this->lastOptionalArgument = null;
+ $this->lastArrayArgument = null;
+ $this->addArguments($arguments);
+ }
+ /**
+ * Adds an array of InputArgument objects.
+ *
+ * @param InputArgument[] $arguments An array of InputArgument objects
+ *
+ * @return void
+ */
+ public function addArguments(?array $arguments = [])
+ {
+ if (null !== $arguments) {
+ foreach ($arguments as $argument) {
+ $this->addArgument($argument);
+ }
+ }
+ }
+ /**
+ * @return void
+ *
+ * @throws LogicException When incorrect argument is given
+ */
+ public function addArgument(InputArgument $argument)
+ {
+ if (isset($this->arguments[$argument->getName()])) {
+ throw new LogicException(\sprintf('An argument with name "%s" already exists.', $argument->getName()));
+ }
+ 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() && 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->lastArrayArgument = $argument;
+ }
+ if ($argument->isRequired()) {
+ ++$this->requiredCount;
+ } else {
+ $this->lastOptionalArgument = $argument;
+ }
+ $this->arguments[$argument->getName()] = $argument;
+ }
+ /**
+ * Returns an InputArgument by name or by position.
+ *
+ * @throws InvalidArgumentException When argument given doesn't exist
+ * @param string|int $name
+ */
+ public function getArgument($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;
+ return $arguments[$name];
+ }
+ /**
+ * Returns true if an InputArgument object exists by name or position.
+ * @param string|int $name
+ */
+ public function hasArgument($name) : bool
+ {
+ $arguments = \is_int($name) ? \array_values($this->arguments) : $this->arguments;
+ return isset($arguments[$name]);
+ }
+ /**
+ * Gets the array of InputArgument objects.
+ *
+ * @return InputArgument[]
+ */
+ public function getArguments() : array
+ {
+ return $this->arguments;
+ }
+ /**
+ * Returns the number of InputArguments.
+ */
+ public function getArgumentCount() : int
+ {
+ return null !== $this->lastArrayArgument ? \PHP_INT_MAX : \count($this->arguments);
+ }
+ /**
+ * Returns the number of required InputArguments.
+ */
+ public function getArgumentRequiredCount() : int
+ {
+ return $this->requiredCount;
+ }
+ /**
+ * @return array
+ */
+ public function getArgumentDefaults() : array
+ {
+ $values = [];
+ foreach ($this->arguments as $argument) {
+ $values[$argument->getName()] = $argument->getDefault();
+ }
+ return $values;
+ }
+ /**
+ * Sets the InputOption objects.
+ *
+ * @param InputOption[] $options An array of InputOption objects
+ *
+ * @return void
+ */
+ public function setOptions(array $options = [])
+ {
+ $this->options = [];
+ $this->shortcuts = [];
+ $this->negations = [];
+ $this->addOptions($options);
+ }
+ /**
+ * Adds an array of InputOption objects.
+ *
+ * @param InputOption[] $options An array of InputOption objects
+ *
+ * @return void
+ */
+ public function addOptions(array $options = [])
+ {
+ foreach ($options as $option) {
+ $this->addOption($option);
+ }
+ }
+ /**
+ * @return void
+ *
+ * @throws LogicException When option given already exist
+ */
+ public function addOption(InputOption $option)
+ {
+ 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) {
+ if (isset($this->shortcuts[$shortcut]) && !$option->equals($this->options[$this->shortcuts[$shortcut]])) {
+ throw new LogicException(\sprintf('An option with shortcut "%s" already exists.', $shortcut));
+ }
+ }
+ }
+ $this->options[$option->getName()] = $option;
+ if ($option->getShortcut()) {
+ foreach (\explode('|', $option->getShortcut()) as $shortcut) {
+ $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.
+ *
+ * @throws InvalidArgumentException When option given doesn't exist
+ */
+ public function getOption(string $name) : InputOption
+ {
+ if (!$this->hasOption($name)) {
+ throw new InvalidArgumentException(\sprintf('The "--%s" option does not exist.', $name));
+ }
+ return $this->options[$name];
+ }
+ /**
+ * Returns true if an InputOption object exists by name.
+ *
+ * This method can't be used to check if the user included the option when
+ * executing the command (use getOption() instead).
+ */
+ public function hasOption(string $name) : bool
+ {
+ return isset($this->options[$name]);
+ }
+ /**
+ * Gets the array of InputOption objects.
+ *
+ * @return InputOption[]
+ */
+ public function getOptions() : array
+ {
+ return $this->options;
+ }
+ /**
+ * Returns true if an InputOption object exists by shortcut.
+ */
+ public function hasShortcut(string $name) : bool
+ {
+ return isset($this->shortcuts[$name]);
+ }
+ /**
+ * Returns true if an InputOption object exists by negated name.
+ */
+ 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));
+ }
+ /**
+ * @return array
+ */
+ public function getOptionDefaults() : array
+ {
+ $values = [];
+ foreach ($this->options as $option) {
+ $values[$option->getName()] = $option->getDefault();
+ }
+ return $values;
+ }
+ /**
+ * Returns the InputOption name given a shortcut.
+ *
+ * @throws InvalidArgumentException When option given does not exist
+ *
+ * @internal
+ */
+ public function shortcutToName(string $shortcut) : string
+ {
+ if (!isset($this->shortcuts[$shortcut])) {
+ throw new InvalidArgumentException(\sprintf('The "-%s" option does not exist.', $shortcut));
+ }
+ return $this->shortcuts[$shortcut];
+ }
+ /**
+ * Returns the InputOption name given a negation.
+ *
+ * @throws InvalidArgumentException When option given does not exist
+ *
+ * @internal
+ */
+ public function negationToName(string $negation) : string
+ {
+ 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]';
+ } elseif (!$short) {
+ foreach ($this->getOptions() as $option) {
+ $value = '';
+ if ($option->acceptValue()) {
+ $value = \sprintf(' %s%s%s', $option->isValueOptional() ? '[' : '', \strtoupper($option->getName()), $option->isValueOptional() ? ']' : '');
+ }
+ $shortcut = $option->getShortcut() ? \sprintf('-%s|', $option->getShortcut()) : '';
+ $negation = $option->isNegatable() ? \sprintf('|--no-%s', $option->getName()) : '';
+ $elements[] = \sprintf('[%s--%s%s%s]', $shortcut, $option->getName(), $value, $negation);
+ }
+ }
+ if (\count($elements) && $this->getArguments()) {
+ $elements[] = '[--]';
+ }
+ $tail = '';
+ foreach ($this->getArguments() as $argument) {
+ $element = '<' . $argument->getName() . '>';
+ if ($argument->isArray()) {
+ $element .= '...';
+ }
+ if (!$argument->isRequired()) {
+ $element = '[' . $element;
+ $tail .= ']';
+ }
+ $elements[] = $element;
+ }
+ return \implode(' ', $elements) . $tail;
+ }
+}
diff --git a/vendor/symfony/console/Input/InputInterface.php b/vendor/symfony/console/Input/InputInterface.php
new file mode 100644
index 00000000..4736141d
--- /dev/null
+++ b/vendor/symfony/console/Input/InputInterface.php
@@ -0,0 +1,136 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Input;
+
+use ClassLeak202307\Symfony\Component\Console\Exception\InvalidArgumentException;
+use ClassLeak202307\Symfony\Component\Console\Exception\RuntimeException;
+/**
+ * InputInterface is the interface implemented by all input classes.
+ *
+ * @author Fabien Potencier
+ *
+ * @method string __toString() Returns a stringified representation of the args passed to the command.
+ * InputArguments MUST be escaped as well as the InputOption values passed to the command.
+ */
+interface InputInterface
+{
+ /**
+ * Returns the first argument from the raw parameters (not parsed).
+ */
+ 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
+ */
+ public function hasParameterOption($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 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
+ */
+ public function getParameterOption($values, $default = \false, bool $onlyParams = \false);
+ /**
+ * Binds the current Input instance with the given arguments and options.
+ *
+ * @return void
+ *
+ * @throws RuntimeException
+ */
+ public function bind(InputDefinition $definition);
+ /**
+ * Validates the input.
+ *
+ * @return void
+ *
+ * @throws RuntimeException When not enough arguments are given
+ */
+ public function validate();
+ /**
+ * Returns all the given arguments merged with the default values.
+ *
+ * @return array
+ */
+ public function getArguments() : array;
+ /**
+ * Returns the argument value for a given argument name.
+ *
+ * @return mixed
+ *
+ * @throws InvalidArgumentException When argument given doesn't exist
+ */
+ public function getArgument(string $name);
+ /**
+ * Sets an argument value by name.
+ *
+ * @return void
+ *
+ * @throws InvalidArgumentException When argument given doesn't exist
+ * @param mixed $value
+ */
+ public function setArgument(string $name, $value);
+ /**
+ * Returns true if an InputArgument object exists by name or position.
+ */
+ public function hasArgument(string $name) : bool;
+ /**
+ * Returns all the given options merged with the default values.
+ *
+ * @return array
+ */
+ public function getOptions() : array;
+ /**
+ * Returns the option value for a given option name.
+ *
+ * @return mixed
+ *
+ * @throws InvalidArgumentException When option given doesn't exist
+ */
+ public function getOption(string $name);
+ /**
+ * Sets an option value by name.
+ *
+ * @return void
+ *
+ * @throws InvalidArgumentException When option given doesn't exist
+ * @param mixed $value
+ */
+ public function setOption(string $name, $value);
+ /**
+ * Returns true if an InputOption object exists by name.
+ */
+ public function hasOption(string $name) : bool;
+ /**
+ * Is this input means interactive?
+ */
+ public function isInteractive() : bool;
+ /**
+ * Sets the input interactivity.
+ *
+ * @return void
+ */
+ public function setInteractive(bool $interactive);
+}
diff --git a/vendor/symfony/console/Input/InputOption.php b/vendor/symfony/console/Input/InputOption.php
new file mode 100644
index 00000000..ab259b6d
--- /dev/null
+++ b/vendor/symfony/console/Input/InputOption.php
@@ -0,0 +1,237 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Input;
+
+use ClassLeak202307\Symfony\Component\Console\Command\Command;
+use ClassLeak202307\Symfony\Component\Console\Completion\CompletionInput;
+use ClassLeak202307\Symfony\Component\Console\Completion\CompletionSuggestions;
+use ClassLeak202307\Symfony\Component\Console\Completion\Suggestion;
+use ClassLeak202307\Symfony\Component\Console\Exception\InvalidArgumentException;
+use ClassLeak202307\Symfony\Component\Console\Exception\LogicException;
+/**
+ * Represents a command line option.
+ *
+ * @author Fabien Potencier
+ */
+class InputOption
+{
+ /**
+ * Do not accept input for the option (e.g. --yell). This is the default behavior of options.
+ */
+ public const VALUE_NONE = 1;
+ /**
+ * 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;
+ /**
+ * @var string
+ */
+ private $name;
+ /**
+ * @var string|mixed[]|null
+ */
+ private $shortcut;
+ /**
+ * @var int
+ */
+ private $mode;
+ /**
+ * @var string|int|bool|mixed[]|null|float
+ */
+ private $default;
+ /**
+ * @var mixed[]|\Closure
+ */
+ private $suggestedValues;
+ /**
+ * @var string
+ */
+ private $description;
+ /**
+ * @param string|mixed[] $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|mixed[] $default The default value (must be null for self::VALUE_NONE)
+ * @param array|\Closure(CompletionInput,CompletionSuggestions):list $suggestedValues The values used for input completion
+ *
+ * @throws InvalidArgumentException If option mode is invalid or incompatible
+ */
+ public function __construct(string $name, $shortcut = null, int $mode = null, string $description = '', $default = null, $suggestedValues = [])
+ {
+ if (\strncmp($name, '--', \strlen('--')) === 0) {
+ $name = \substr($name, 2);
+ }
+ if (empty($name)) {
+ throw new InvalidArgumentException('An option name cannot be empty.');
+ }
+ if (empty($shortcut)) {
+ $shortcut = null;
+ }
+ if (null !== $shortcut) {
+ if (\is_array($shortcut)) {
+ $shortcut = \implode('|', $shortcut);
+ }
+ $shortcuts = \preg_split('{(\\|)-?}', \ltrim($shortcut, '-'));
+ $shortcuts = \array_filter($shortcuts);
+ $shortcut = \implode('|', $shortcuts);
+ if (empty($shortcut)) {
+ throw new InvalidArgumentException('An option shortcut cannot be empty.');
+ }
+ }
+ if (null === $mode) {
+ $mode = self::VALUE_NONE;
+ } elseif ($mode >= self::VALUE_NEGATABLE << 1 || $mode < 1) {
+ throw new InvalidArgumentException(\sprintf('Option mode "%s" is not valid.', $mode));
+ }
+ $this->name = $name;
+ $this->shortcut = $shortcut;
+ $this->mode = $mode;
+ $this->description = $description;
+ $this->suggestedValues = $suggestedValues;
+ if ($suggestedValues && !$this->acceptValue()) {
+ throw new LogicException('Cannot set suggested values if the option does not accept a value.');
+ }
+ 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.
+ */
+ public function getShortcut() : ?string
+ {
+ return $this->shortcut;
+ }
+ /**
+ * Returns the option name.
+ */
+ public function getName() : string
+ {
+ return $this->name;
+ }
+ /**
+ * Returns true if the option accepts a value.
+ *
+ * @return bool true if value mode is not self::VALUE_NONE, false otherwise
+ */
+ public function acceptValue() : bool
+ {
+ return $this->isValueRequired() || $this->isValueOptional();
+ }
+ /**
+ * Returns true if the option requires a value.
+ *
+ * @return bool true if value mode is self::VALUE_REQUIRED, false otherwise
+ */
+ public function isValueRequired() : bool
+ {
+ return self::VALUE_REQUIRED === (self::VALUE_REQUIRED & $this->mode);
+ }
+ /**
+ * Returns true if the option takes an optional value.
+ *
+ * @return bool true if value mode is self::VALUE_OPTIONAL, false otherwise
+ */
+ public function isValueOptional() : bool
+ {
+ return self::VALUE_OPTIONAL === (self::VALUE_OPTIONAL & $this->mode);
+ }
+ /**
+ * Returns true if the option can take multiple values.
+ *
+ * @return bool true if mode is self::VALUE_IS_ARRAY, false otherwise
+ */
+ public function isArray() : bool
+ {
+ return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode);
+ }
+ public function isNegatable() : bool
+ {
+ return self::VALUE_NEGATABLE === (self::VALUE_NEGATABLE & $this->mode);
+ }
+ /**
+ * @return void
+ * @param string|bool|int|float|mixed[] $default
+ */
+ public function setDefault($default = null)
+ {
+ if (1 > \func_num_args()) {
+ trigger_deprecation('symfony/console', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
+ }
+ 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.');
+ }
+ if ($this->isArray()) {
+ if (null === $default) {
+ $default = [];
+ } elseif (!\is_array($default)) {
+ throw new LogicException('A default value for an array option must be an array.');
+ }
+ }
+ $this->default = $this->acceptValue() || $this->isNegatable() ? $default : \false;
+ }
+ /**
+ * Returns the default value.
+ * @return string|bool|int|float|mixed[]|null
+ */
+ public function getDefault()
+ {
+ return $this->default;
+ }
+ /**
+ * Returns the description text.
+ */
+ public function getDescription() : string
+ {
+ return $this->description;
+ }
+ public function hasCompletion() : bool
+ {
+ return [] !== $this->suggestedValues;
+ }
+ /**
+ * Adds suggestions to $suggestions for the current completion input.
+ *
+ * @see Command::complete()
+ */
+ public function complete(CompletionInput $input, CompletionSuggestions $suggestions) : void
+ {
+ $values = $this->suggestedValues;
+ if ($values instanceof \Closure && !\is_array($values = $values($input))) {
+ throw new LogicException(\sprintf('Closure for option "%s" must return an array. Got "%s".', $this->name, \get_debug_type($values)));
+ }
+ if ($values) {
+ $suggestions->suggestValues($values);
+ }
+ }
+ /**
+ * Checks whether the given option equals this one.
+ */
+ 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();
+ }
+}
diff --git a/vendor/symfony/console/Input/StreamableInputInterface.php b/vendor/symfony/console/Input/StreamableInputInterface.php
new file mode 100644
index 00000000..1e9784a1
--- /dev/null
+++ b/vendor/symfony/console/Input/StreamableInputInterface.php
@@ -0,0 +1,37 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Input;
+
+/**
+ * StreamableInputInterface is the interface implemented by all input classes
+ * that have an input stream.
+ *
+ * @author Robin Chalas
+ */
+interface StreamableInputInterface extends InputInterface
+{
+ /**
+ * Sets the input stream to read from when interacting with the user.
+ *
+ * This is mainly useful for testing purpose.
+ *
+ * @param resource $stream The input stream
+ *
+ * @return void
+ */
+ public function setStream($stream);
+ /**
+ * Returns the input stream.
+ *
+ * @return resource|null
+ */
+ public function getStream();
+}
diff --git a/vendor/symfony/console/Input/StringInput.php b/vendor/symfony/console/Input/StringInput.php
new file mode 100644
index 00000000..e38ee6ef
--- /dev/null
+++ b/vendor/symfony/console/Input/StringInput.php
@@ -0,0 +1,78 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Input;
+
+use ClassLeak202307\Symfony\Component\Console\Exception\InvalidArgumentException;
+/**
+ * StringInput represents an input provided as a string.
+ *
+ * Usage:
+ *
+ * $input = new StringInput('foo --bar="foobar"');
+ *
+ * @author Fabien Potencier
+ */
+class StringInput extends ArgvInput
+{
+ /**
+ * @deprecated since Symfony 6.1
+ */
+ public const REGEX_STRING = '([^\\s]+?)(?:\\s|(?setTokens($this->tokenize($input));
+ }
+ /**
+ * Tokenizes a string.
+ *
+ * @throws InvalidArgumentException When unable to parse input (should never happen)
+ */
+ private function tokenize(string $input) : array
+ {
+ $tokens = [];
+ $length = \strlen($input);
+ $cursor = 0;
+ $token = null;
+ while ($cursor < $length) {
+ if ('\\' === $input[$cursor]) {
+ $token .= $input[++$cursor] ?? '';
+ ++$cursor;
+ continue;
+ }
+ 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;
+ }
+}
diff --git a/vendor/symfony/console/LICENSE b/vendor/symfony/console/LICENSE
new file mode 100644
index 00000000..0138f8f0
--- /dev/null
+++ b/vendor/symfony/console/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2004-present 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
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/symfony/console/Logger/ConsoleLogger.php b/vendor/symfony/console/Logger/ConsoleLogger.php
new file mode 100644
index 00000000..d99c1891
--- /dev/null
+++ b/vendor/symfony/console/Logger/ConsoleLogger.php
@@ -0,0 +1,101 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Logger;
+
+use ClassLeak202307\Psr\Log\AbstractLogger;
+use ClassLeak202307\Psr\Log\InvalidArgumentException;
+use ClassLeak202307\Psr\Log\LogLevel;
+use ClassLeak202307\Symfony\Component\Console\Output\ConsoleOutputInterface;
+use ClassLeak202307\Symfony\Component\Console\Output\OutputInterface;
+/**
+ * PSR-3 compliant console logger.
+ *
+ * @author Kévin Dunglas
+ *
+ * @see https://www.php-fig.org/psr/psr-3/
+ */
+class ConsoleLogger extends AbstractLogger
+{
+ public const INFO = 'info';
+ public const ERROR = 'error';
+ /**
+ * @var \Symfony\Component\Console\Output\OutputInterface
+ */
+ private $output;
+ /**
+ * @var mixed[]
+ */
+ private $verbosityLevelMap = [LogLevel::EMERGENCY => OutputInterface::VERBOSITY_NORMAL, LogLevel::ALERT => OutputInterface::VERBOSITY_NORMAL, LogLevel::CRITICAL => OutputInterface::VERBOSITY_NORMAL, LogLevel::ERROR => OutputInterface::VERBOSITY_NORMAL, LogLevel::WARNING => OutputInterface::VERBOSITY_NORMAL, LogLevel::NOTICE => OutputInterface::VERBOSITY_VERBOSE, LogLevel::INFO => OutputInterface::VERBOSITY_VERY_VERBOSE, LogLevel::DEBUG => OutputInterface::VERBOSITY_DEBUG];
+ /**
+ * @var mixed[]
+ */
+ private $formatLevelMap = [LogLevel::EMERGENCY => self::ERROR, LogLevel::ALERT => self::ERROR, LogLevel::CRITICAL => self::ERROR, LogLevel::ERROR => self::ERROR, LogLevel::WARNING => self::INFO, LogLevel::NOTICE => self::INFO, LogLevel::INFO => self::INFO, LogLevel::DEBUG => self::INFO];
+ /**
+ * @var bool
+ */
+ private $errored = \false;
+ public function __construct(OutputInterface $output, array $verbosityLevelMap = [], array $formatLevelMap = [])
+ {
+ $this->output = $output;
+ $this->verbosityLevelMap = $verbosityLevelMap + $this->verbosityLevelMap;
+ $this->formatLevelMap = $formatLevelMap + $this->formatLevelMap;
+ }
+ 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));
+ }
+ $output = $this->output;
+ // Write to the error output if necessary and available
+ if (self::ERROR === $this->formatLevelMap[$level]) {
+ if ($this->output instanceof ConsoleOutputInterface) {
+ $output = $output->getErrorOutput();
+ }
+ $this->errored = \true;
+ }
+ // the if condition check isn't necessary -- it's the same one that $output will do internally anyway.
+ // We only do it for efficiency here as the message formatting is relatively expensive.
+ if ($output->getVerbosity() >= $this->verbosityLevelMap[$level]) {
+ $output->writeln(\sprintf('<%1$s>[%2$s] %3$s%1$s>', $this->formatLevelMap[$level], $level, $this->interpolate($message, $context)), $this->verbosityLevelMap[$level]);
+ }
+ }
+ /**
+ * Returns true when any messages have been logged at error levels.
+ */
+ public function hasErrored() : bool
+ {
+ return $this->errored;
+ }
+ /**
+ * Interpolates context values into the message placeholders.
+ *
+ * @author PHP Framework Interoperability Group
+ */
+ private function interpolate(string $message, array $context) : string
+ {
+ if (\strpos($message, '{') === \false) {
+ return $message;
+ }
+ $replacements = [];
+ foreach ($context as $key => $val) {
+ if (null === $val || \is_scalar($val) || $val instanceof \Stringable) {
+ $replacements["{{$key}}"] = $val;
+ } elseif ($val instanceof \DateTimeInterface) {
+ $replacements["{{$key}}"] = $val->format(\DateTimeInterface::RFC3339);
+ } elseif (\is_object($val)) {
+ $replacements["{{$key}}"] = '[object ' . \get_class($val) . ']';
+ } else {
+ $replacements["{{$key}}"] = '[' . \gettype($val) . ']';
+ }
+ }
+ return \strtr($message, $replacements);
+ }
+}
diff --git a/vendor/symfony/console/Output/AnsiColorMode.php b/vendor/symfony/console/Output/AnsiColorMode.php
new file mode 100644
index 00000000..fca9d736
--- /dev/null
+++ b/vendor/symfony/console/Output/AnsiColorMode.php
@@ -0,0 +1,76 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Output;
+
+use ClassLeak202307\Symfony\Component\Console\Exception\InvalidArgumentException;
+class AnsiColorMode
+{
+ public const Ansi4 = 'ansi4';
+ public const Ansi8 = 'ansi8';
+ public const Ansi24 = 'ansi24';
+ /**
+ * Converts an RGB hexadecimal color to the corresponding Ansi code.
+ */
+ public function convertFromHexToAnsiColorCode(string $hexColor) : string
+ {
+ $hexColor = \str_replace('#', '', $hexColor);
+ if (3 === \strlen($hexColor)) {
+ $hexColor = $hexColor[0] . $hexColor[0] . $hexColor[1] . $hexColor[1] . $hexColor[2] . $hexColor[2];
+ }
+ if (6 !== \strlen($hexColor)) {
+ throw new InvalidArgumentException(\sprintf('Invalid "#%s" color.', $hexColor));
+ }
+ $color = \hexdec($hexColor);
+ $r = $color >> 16 & 255;
+ $g = $color >> 8 & 255;
+ $b = $color & 255;
+ switch ($this) {
+ case self::Ansi4:
+ return (string) $this->convertFromRGB($r, $g, $b);
+ case self::Ansi8:
+ return '8;5;' . (string) $this->convertFromRGB($r, $g, $b);
+ case self::Ansi24:
+ return \sprintf('8;2;%d;%d;%d', $r, $g, $b);
+ }
+ }
+ private function convertFromRGB(int $r, int $g, int $b) : int
+ {
+ switch ($this) {
+ case self::Ansi4:
+ return $this->degradeHexColorToAnsi4($r, $g, $b);
+ case self::Ansi8:
+ return $this->degradeHexColorToAnsi8($r, $g, $b);
+ default:
+ throw new InvalidArgumentException("RGB cannot be converted to {$this->name}.");
+ }
+ }
+ private function degradeHexColorToAnsi4(int $r, int $g, int $b) : int
+ {
+ return \round($b / 255) << 2 | \round($g / 255) << 1 | \round($r / 255);
+ }
+ /**
+ * Inspired from https://github.com/ajalt/colormath/blob/e464e0da1b014976736cf97250063248fc77b8e7/colormath/src/commonMain/kotlin/com/github/ajalt/colormath/model/Ansi256.kt code (MIT license).
+ */
+ private function degradeHexColorToAnsi8(int $r, int $g, int $b) : int
+ {
+ if ($r === $g && $g === $b) {
+ if ($r < 8) {
+ return 16;
+ }
+ if ($r > 248) {
+ return 231;
+ }
+ return (int) \round(($r - 8) / 247 * 24) + 232;
+ } else {
+ return 16 + 36 * (int) \round($r / 255 * 5) + 6 * (int) \round($g / 255 * 5) + (int) \round($b / 255 * 5);
+ }
+ }
+}
diff --git a/vendor/symfony/console/Output/BufferedOutput.php b/vendor/symfony/console/Output/BufferedOutput.php
new file mode 100644
index 00000000..029cbbf6
--- /dev/null
+++ b/vendor/symfony/console/Output/BufferedOutput.php
@@ -0,0 +1,41 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Output;
+
+/**
+ * @author Jean-François Simon
+ */
+class BufferedOutput extends Output
+{
+ /**
+ * @var string
+ */
+ private $buffer = '';
+ /**
+ * Empties buffer and returns its content.
+ */
+ public function fetch() : string
+ {
+ $content = $this->buffer;
+ $this->buffer = '';
+ return $content;
+ }
+ /**
+ * @return void
+ */
+ protected function doWrite(string $message, bool $newline)
+ {
+ $this->buffer .= $message;
+ if ($newline) {
+ $this->buffer .= \PHP_EOL;
+ }
+ }
+}
diff --git a/vendor/symfony/console/Output/ConsoleOutput.php b/vendor/symfony/console/Output/ConsoleOutput.php
new file mode 100644
index 00000000..8557439f
--- /dev/null
+++ b/vendor/symfony/console/Output/ConsoleOutput.php
@@ -0,0 +1,146 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Output;
+
+use ClassLeak202307\Symfony\Component\Console\Formatter\OutputFormatterInterface;
+/**
+ * ConsoleOutput is the default class for all CLI output. It uses STDOUT and STDERR.
+ *
+ * This class is a convenient wrapper around `StreamOutput` for both STDOUT and STDERR.
+ *
+ * $output = new ConsoleOutput();
+ *
+ * This is equivalent to:
+ *
+ * $output = new StreamOutput(fopen('php://stdout', 'w'));
+ * $stdErr = new StreamOutput(fopen('php://stderr', 'w'));
+ *
+ * @author Fabien Potencier
+ */
+class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface
+{
+ /**
+ * @var \Symfony\Component\Console\Output\OutputInterface
+ */
+ private $stderr;
+ /**
+ * @var mixed[]
+ */
+ private $consoleSectionOutputs = [];
+ /**
+ * @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(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());
+ if (null === $decorated) {
+ $this->setDecorated($actualDecorated && $this->stderr->isDecorated());
+ }
+ }
+ /**
+ * Creates a new output section.
+ */
+ public function section() : ConsoleSectionOutput
+ {
+ return new ConsoleSectionOutput($this->getStream(), $this->consoleSectionOutputs, $this->getVerbosity(), $this->isDecorated(), $this->getFormatter());
+ }
+ /**
+ * @return void
+ */
+ public function setDecorated(bool $decorated)
+ {
+ parent::setDecorated($decorated);
+ $this->stderr->setDecorated($decorated);
+ }
+ /**
+ * @return void
+ */
+ public function setFormatter(OutputFormatterInterface $formatter)
+ {
+ parent::setFormatter($formatter);
+ $this->stderr->setFormatter($formatter);
+ }
+ /**
+ * @return void
+ */
+ public function setVerbosity(int $level)
+ {
+ parent::setVerbosity($level);
+ $this->stderr->setVerbosity($level);
+ }
+ public function getErrorOutput() : OutputInterface
+ {
+ return $this->stderr;
+ }
+ /**
+ * @return void
+ */
+ public function setErrorOutput(OutputInterface $error)
+ {
+ $this->stderr = $error;
+ }
+ /**
+ * Returns true if current environment supports writing console output to
+ * STDOUT.
+ */
+ protected function hasStdoutSupport() : bool
+ {
+ return \false === $this->isRunningOS400();
+ }
+ /**
+ * Returns true if current environment supports writing console output to
+ * STDERR.
+ */
+ protected function hasStderrSupport() : bool
+ {
+ return \false === $this->isRunningOS400();
+ }
+ /**
+ * Checks if current executing environment is IBM iSeries (OS400), which
+ * doesn't properly convert character-encodings between ASCII to EBCDIC.
+ */
+ private function isRunningOS400() : bool
+ {
+ $checks = [\function_exists('php_uname') ? \php_uname('s') : '', \getenv('OSTYPE'), \PHP_OS];
+ return \false !== \stripos(\implode(';', $checks), 'OS400');
+ }
+ /**
+ * @return resource
+ */
+ private function openOutputStream()
+ {
+ if (!$this->hasStdoutSupport()) {
+ return \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'));
+ }
+ /**
+ * @return resource
+ */
+ private function openErrorStream()
+ {
+ 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'));
+ }
+}
diff --git a/vendor/symfony/console/Output/ConsoleOutputInterface.php b/vendor/symfony/console/Output/ConsoleOutputInterface.php
new file mode 100644
index 00000000..b73f5595
--- /dev/null
+++ b/vendor/symfony/console/Output/ConsoleOutputInterface.php
@@ -0,0 +1,30 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Output;
+
+/**
+ * ConsoleOutputInterface is the interface implemented by ConsoleOutput class.
+ * This adds information about stderr and section output stream.
+ *
+ * @author Dariusz Górecki
+ */
+interface ConsoleOutputInterface extends OutputInterface
+{
+ /**
+ * Gets the OutputInterface for errors.
+ */
+ public function getErrorOutput() : OutputInterface;
+ /**
+ * @return void
+ */
+ public function setErrorOutput(OutputInterface $error);
+ public function section() : ConsoleSectionOutput;
+}
diff --git a/vendor/symfony/console/Output/ConsoleSectionOutput.php b/vendor/symfony/console/Output/ConsoleSectionOutput.php
new file mode 100644
index 00000000..024b857c
--- /dev/null
+++ b/vendor/symfony/console/Output/ConsoleSectionOutput.php
@@ -0,0 +1,217 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Output;
+
+use ClassLeak202307\Symfony\Component\Console\Formatter\OutputFormatterInterface;
+use ClassLeak202307\Symfony\Component\Console\Helper\Helper;
+use ClassLeak202307\Symfony\Component\Console\Terminal;
+/**
+ * @author Pierre du Plessis
+ * @author Gabriel Ostrolucký
+ */
+class ConsoleSectionOutput extends StreamOutput
+{
+ /**
+ * @var mixed[]
+ */
+ private $content = [];
+ /**
+ * @var int
+ */
+ private $lines = 0;
+ /**
+ * @var mixed[]
+ */
+ private $sections;
+ /**
+ * @var \Symfony\Component\Console\Terminal
+ */
+ private $terminal;
+ /**
+ * @var int
+ */
+ private $maxHeight = 0;
+ /**
+ * @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();
+ }
+ /**
+ * Defines a maximum number of lines for this section.
+ *
+ * When more lines are added, the section will automatically scroll to the
+ * end (i.e. remove the first lines to comply with the max height).
+ */
+ public function setMaxHeight(int $maxHeight) : void
+ {
+ // when changing max height, clear output of current section and redraw again with the new height
+ $existingContent = $this->popStreamContentUntilCurrentSection($this->maxHeight ? \min($this->maxHeight, $this->lines) : $this->lines);
+ $this->maxHeight = $maxHeight;
+ parent::doWrite($this->getVisibleContent(), \false);
+ parent::doWrite($existingContent, \false);
+ }
+ /**
+ * 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
+ *
+ * @return void
+ */
+ public function clear(int $lines = null)
+ {
+ if (empty($this->content) || !$this->isDecorated()) {
+ return;
+ }
+ if ($lines) {
+ \array_splice($this->content, -$lines);
+ } else {
+ $lines = $this->lines;
+ $this->content = [];
+ }
+ $this->lines -= $lines;
+ parent::doWrite($this->popStreamContentUntilCurrentSection($this->maxHeight ? \min($this->maxHeight, $lines) : $lines), \false);
+ }
+ /**
+ * Overwrites the previous output with a new message.
+ *
+ * @return void
+ * @param string|mixed[] $message
+ */
+ public function overwrite($message)
+ {
+ $this->clear();
+ $this->writeln($message);
+ }
+ public function getContent() : string
+ {
+ return \implode('', $this->content);
+ }
+ public function getVisibleContent() : string
+ {
+ if (0 === $this->maxHeight) {
+ return $this->getContent();
+ }
+ return \implode('', \array_slice($this->content, -$this->maxHeight));
+ }
+ /**
+ * @internal
+ */
+ public function addContent(string $input, bool $newline = \true) : int
+ {
+ $width = $this->terminal->getWidth();
+ $lines = \explode(\PHP_EOL, $input);
+ $linesAdded = 0;
+ $count = \count($lines) - 1;
+ foreach ($lines as $i => $lineContent) {
+ // re-add the line break (that has been removed in the above `explode()` for
+ // - every line that is not the last line
+ // - if $newline is required, also add it to the last line
+ // - if it's not new line, but input ending with `\PHP_EOL`
+ if ($i < $count || $newline || \substr_compare($input, \PHP_EOL, -\strlen(\PHP_EOL)) === 0) {
+ $lineContent .= \PHP_EOL;
+ }
+ // skip line if there is no text (or newline for that matter)
+ if ('' === $lineContent) {
+ continue;
+ }
+ // For the first line, check if the previous line (last entry of `$this->content`)
+ // needs to be continued (i.e. does not end with a line break).
+ if (0 === $i && \false !== ($lastLine = \end($this->content)) && \substr_compare($lastLine, \PHP_EOL, -\strlen(\PHP_EOL)) !== 0) {
+ // deduct the line count of the previous line
+ $this->lines -= (int) \ceil($this->getDisplayLength($lastLine) / $width) ?: 1;
+ // concatenate previous and new line
+ $lineContent = $lastLine . $lineContent;
+ // replace last entry of `$this->content` with the new expanded line
+ \array_splice($this->content, -1, 1, $lineContent);
+ } else {
+ // otherwise just add the new content
+ $this->content[] = $lineContent;
+ }
+ $linesAdded += (int) \ceil($this->getDisplayLength($lineContent) / $width) ?: 1;
+ }
+ $this->lines += $linesAdded;
+ return $linesAdded;
+ }
+ /**
+ * @internal
+ */
+ public function addNewLineOfInputSubmit() : void
+ {
+ $this->content[] = \PHP_EOL;
+ ++$this->lines;
+ }
+ /**
+ * @return void
+ */
+ protected function doWrite(string $message, bool $newline)
+ {
+ if (!$this->isDecorated()) {
+ parent::doWrite($message, $newline);
+ return;
+ }
+ // Check if the previous line (last entry of `$this->content`) needs to be continued
+ // (i.e. does not end with a line break). In which case, it needs to be erased first.
+ $linesToClear = $deleteLastLine = ($lastLine = \end($this->content) ?: '') && \substr_compare($lastLine, \PHP_EOL, -\strlen(\PHP_EOL)) !== 0 ? 1 : 0;
+ $linesAdded = $this->addContent($message, $newline);
+ if ($lineOverflow = $this->maxHeight > 0 && $this->lines > $this->maxHeight) {
+ // on overflow, clear the whole section and redraw again (to remove the first lines)
+ $linesToClear = $this->maxHeight;
+ }
+ $erasedContent = $this->popStreamContentUntilCurrentSection($linesToClear);
+ if ($lineOverflow) {
+ // redraw existing lines of the section
+ $previousLinesOfSection = \array_slice($this->content, $this->lines - $this->maxHeight, $this->maxHeight - $linesAdded);
+ parent::doWrite(\implode('', $previousLinesOfSection), \false);
+ }
+ // if the last line was removed, re-print its content together with the new content.
+ // otherwise, just print the new content.
+ parent::doWrite($deleteLastLine ? $lastLine . $message : $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;
+ if ('' !== ($sectionContent = $section->getVisibleContent())) {
+ if (\substr_compare($sectionContent, \PHP_EOL, -\strlen(\PHP_EOL)) !== 0) {
+ $sectionContent .= \PHP_EOL;
+ }
+ $erasedContent[] = $sectionContent;
+ }
+ }
+ 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)));
+ }
+}
diff --git a/vendor/symfony/console/Output/NullOutput.php b/vendor/symfony/console/Output/NullOutput.php
new file mode 100644
index 00000000..2c4dafbd
--- /dev/null
+++ b/vendor/symfony/console/Output/NullOutput.php
@@ -0,0 +1,95 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Output;
+
+use ClassLeak202307\Symfony\Component\Console\Formatter\NullOutputFormatter;
+use ClassLeak202307\Symfony\Component\Console\Formatter\OutputFormatterInterface;
+/**
+ * NullOutput suppresses all output.
+ *
+ * $output = new NullOutput();
+ *
+ * @author Fabien Potencier
+ * @author Tobias Schultze
+ */
+class NullOutput implements OutputInterface
+{
+ /**
+ * @var \Symfony\Component\Console\Formatter\NullOutputFormatter
+ */
+ private $formatter;
+ /**
+ * @return void
+ */
+ public function setFormatter(OutputFormatterInterface $formatter)
+ {
+ // do nothing
+ }
+ public function getFormatter() : OutputFormatterInterface
+ {
+ // to comply with the interface we must return a OutputFormatterInterface
+ return $this->formatter = $this->formatter ?? new NullOutputFormatter();
+ }
+ /**
+ * @return void
+ */
+ public function setDecorated(bool $decorated)
+ {
+ // do nothing
+ }
+ public function isDecorated() : bool
+ {
+ return \false;
+ }
+ /**
+ * @return void
+ */
+ public function setVerbosity(int $level)
+ {
+ // do nothing
+ }
+ public function getVerbosity() : int
+ {
+ return self::VERBOSITY_QUIET;
+ }
+ public function isQuiet() : bool
+ {
+ return \true;
+ }
+ public function isVerbose() : bool
+ {
+ return \false;
+ }
+ public function isVeryVerbose() : bool
+ {
+ return \false;
+ }
+ public function isDebug() : bool
+ {
+ return \false;
+ }
+ /**
+ * @return void
+ * @param string|mixed[] $messages
+ */
+ public function writeln($messages, int $options = self::OUTPUT_NORMAL)
+ {
+ // do nothing
+ }
+ /**
+ * @return void
+ * @param string|mixed[] $messages
+ */
+ public function write($messages, bool $newline = \false, int $options = self::OUTPUT_NORMAL)
+ {
+ // do nothing
+ }
+}
diff --git a/vendor/symfony/console/Output/Output.php b/vendor/symfony/console/Output/Output.php
new file mode 100644
index 00000000..612209de
--- /dev/null
+++ b/vendor/symfony/console/Output/Output.php
@@ -0,0 +1,142 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Output;
+
+use ClassLeak202307\Symfony\Component\Console\Formatter\OutputFormatter;
+use ClassLeak202307\Symfony\Component\Console\Formatter\OutputFormatterInterface;
+/**
+ * Base class for output classes.
+ *
+ * There are five levels of verbosity:
+ *
+ * * normal: no option passed (normal output)
+ * * verbose: -v (more output)
+ * * very verbose: -vv (highly extended output)
+ * * debug: -vvv (all debug output)
+ * * quiet: -q (no output)
+ *
+ * @author Fabien Potencier
+ */
+abstract class Output implements OutputInterface
+{
+ /**
+ * @var int
+ */
+ private $verbosity;
+ /**
+ * @var \Symfony\Component\Console\Formatter\OutputFormatterInterface
+ */
+ private $formatter;
+ /**
+ * @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(?int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = \false, OutputFormatterInterface $formatter = null)
+ {
+ $this->verbosity = $verbosity ?? self::VERBOSITY_NORMAL;
+ $this->formatter = $formatter ?? new OutputFormatter();
+ $this->formatter->setDecorated($decorated);
+ }
+ /**
+ * @return void
+ */
+ public function setFormatter(OutputFormatterInterface $formatter)
+ {
+ $this->formatter = $formatter;
+ }
+ public function getFormatter() : OutputFormatterInterface
+ {
+ return $this->formatter;
+ }
+ /**
+ * @return void
+ */
+ public function setDecorated(bool $decorated)
+ {
+ $this->formatter->setDecorated($decorated);
+ }
+ public function isDecorated() : bool
+ {
+ return $this->formatter->isDecorated();
+ }
+ /**
+ * @return void
+ */
+ public function setVerbosity(int $level)
+ {
+ $this->verbosity = $level;
+ }
+ public function getVerbosity() : int
+ {
+ return $this->verbosity;
+ }
+ public function isQuiet() : bool
+ {
+ return self::VERBOSITY_QUIET === $this->verbosity;
+ }
+ public function isVerbose() : bool
+ {
+ return self::VERBOSITY_VERBOSE <= $this->verbosity;
+ }
+ public function isVeryVerbose() : bool
+ {
+ return self::VERBOSITY_VERY_VERBOSE <= $this->verbosity;
+ }
+ public function isDebug() : bool
+ {
+ return self::VERBOSITY_DEBUG <= $this->verbosity;
+ }
+ /**
+ * @return void
+ * @param string|mixed[] $messages
+ */
+ public function writeln($messages, int $options = self::OUTPUT_NORMAL)
+ {
+ $this->write($messages, \true, $options);
+ }
+ /**
+ * @return void
+ * @param string|mixed[] $messages
+ */
+ public function write($messages, bool $newline = \false, int $options = self::OUTPUT_NORMAL)
+ {
+ if (!\is_iterable($messages)) {
+ $messages = [$messages];
+ }
+ $types = self::OUTPUT_NORMAL | self::OUTPUT_RAW | self::OUTPUT_PLAIN;
+ $type = $types & $options ?: self::OUTPUT_NORMAL;
+ $verbosities = self::VERBOSITY_QUIET | self::VERBOSITY_NORMAL | self::VERBOSITY_VERBOSE | self::VERBOSITY_VERY_VERBOSE | self::VERBOSITY_DEBUG;
+ $verbosity = $verbosities & $options ?: self::VERBOSITY_NORMAL;
+ if ($verbosity > $this->getVerbosity()) {
+ return;
+ }
+ foreach ($messages as $message) {
+ switch ($type) {
+ case OutputInterface::OUTPUT_NORMAL:
+ $message = $this->formatter->format($message);
+ break;
+ case OutputInterface::OUTPUT_RAW:
+ break;
+ case OutputInterface::OUTPUT_PLAIN:
+ $message = \strip_tags($this->formatter->format($message));
+ break;
+ }
+ $this->doWrite($message ?? '', $newline);
+ }
+ }
+ /**
+ * Writes a message to the output.
+ *
+ * @return void
+ */
+ protected abstract function doWrite(string $message, bool $newline);
+}
diff --git a/vendor/symfony/console/Output/OutputInterface.php b/vendor/symfony/console/Output/OutputInterface.php
new file mode 100644
index 00000000..0bef8042
--- /dev/null
+++ b/vendor/symfony/console/Output/OutputInterface.php
@@ -0,0 +1,94 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Output;
+
+use ClassLeak202307\Symfony\Component\Console\Formatter\OutputFormatterInterface;
+/**
+ * OutputInterface is the interface implemented by all Output classes.
+ *
+ * @author Fabien Potencier
+ */
+interface OutputInterface
+{
+ 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;
+ public const OUTPUT_NORMAL = 1;
+ public const OUTPUT_RAW = 2;
+ public const OUTPUT_PLAIN = 4;
+ /**
+ * Writes a message to the output.
+ *
+ * @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
+ *
+ * @return void
+ * @param string|mixed[] $messages
+ */
+ public function write($messages, bool $newline = \false, int $options = 0);
+ /**
+ * Writes a message to the output and adds a newline at the end.
+ *
+ * @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
+ *
+ * @return void
+ * @param string|mixed[] $messages
+ */
+ public function writeln($messages, int $options = 0);
+ /**
+ * Sets the verbosity of the output.
+ *
+ * @return void
+ */
+ public function setVerbosity(int $level);
+ /**
+ * Gets the current verbosity of the output.
+ */
+ public function getVerbosity() : int;
+ /**
+ * Returns whether verbosity is quiet (-q).
+ */
+ public function isQuiet() : bool;
+ /**
+ * Returns whether verbosity is verbose (-v).
+ */
+ public function isVerbose() : bool;
+ /**
+ * Returns whether verbosity is very verbose (-vv).
+ */
+ public function isVeryVerbose() : bool;
+ /**
+ * Returns whether verbosity is debug (-vvv).
+ */
+ public function isDebug() : bool;
+ /**
+ * Sets the decorated flag.
+ *
+ * @return void
+ */
+ public function setDecorated(bool $decorated);
+ /**
+ * Gets the decorated flag.
+ */
+ public function isDecorated() : bool;
+ /**
+ * @return void
+ */
+ public function setFormatter(OutputFormatterInterface $formatter);
+ /**
+ * Returns current output formatter instance.
+ */
+ public function getFormatter() : OutputFormatterInterface;
+}
diff --git a/vendor/symfony/console/Output/StreamOutput.php b/vendor/symfony/console/Output/StreamOutput.php
new file mode 100644
index 00000000..c36dd34a
--- /dev/null
+++ b/vendor/symfony/console/Output/StreamOutput.php
@@ -0,0 +1,95 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Output;
+
+use ClassLeak202307\Symfony\Component\Console\Exception\InvalidArgumentException;
+use ClassLeak202307\Symfony\Component\Console\Formatter\OutputFormatterInterface;
+/**
+ * StreamOutput writes the output to a given stream.
+ *
+ * Usage:
+ *
+ * $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));
+ *
+ * @author Fabien Potencier
+ */
+class StreamOutput extends Output
+{
+ private $stream;
+ /**
+ * @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)
+ * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter)
+ *
+ * @throws InvalidArgumentException When first argument is not a real stream
+ */
+ public function __construct($stream, int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = null, OutputFormatterInterface $formatter = null)
+ {
+ if (!\is_resource($stream) || 'stream' !== \get_resource_type($stream)) {
+ throw new InvalidArgumentException('The StreamOutput class needs a stream as its first argument.');
+ }
+ $this->stream = $stream;
+ $decorated = $decorated ?? $this->hasColorSupport();
+ parent::__construct($verbosity, $decorated, $formatter);
+ }
+ /**
+ * Gets the stream attached to this StreamOutput instance.
+ *
+ * @return resource
+ */
+ public function getStream()
+ {
+ return $this->stream;
+ }
+ /**
+ * @return void
+ */
+ protected function doWrite(string $message, bool $newline)
+ {
+ if ($newline) {
+ $message .= \PHP_EOL;
+ }
+ @\fwrite($this->stream, $message);
+ \fflush($this->stream);
+ }
+ /**
+ * Returns true if the stream supports colorization.
+ *
+ * Colorization is disabled if not supported by the stream:
+ *
+ * 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() : bool
+ {
+ // 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 \stream_isatty($this->stream);
+ }
+}
diff --git a/vendor/symfony/console/Output/TrimmedBufferOutput.php b/vendor/symfony/console/Output/TrimmedBufferOutput.php
new file mode 100644
index 00000000..10bb60d8
--- /dev/null
+++ b/vendor/symfony/console/Output/TrimmedBufferOutput.php
@@ -0,0 +1,58 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Output;
+
+use ClassLeak202307\Symfony\Component\Console\Exception\InvalidArgumentException;
+use ClassLeak202307\Symfony\Component\Console\Formatter\OutputFormatterInterface;
+/**
+ * A BufferedOutput that keeps only the last N chars.
+ *
+ * @author Jérémy Derussé
+ */
+class TrimmedBufferOutput extends Output
+{
+ /**
+ * @var int
+ */
+ private $maxLength;
+ /**
+ * @var string
+ */
+ private $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;
+ }
+ /**
+ * @return void
+ */
+ protected function doWrite(string $message, bool $newline)
+ {
+ $this->buffer .= $message;
+ if ($newline) {
+ $this->buffer .= \PHP_EOL;
+ }
+ $this->buffer = \substr($this->buffer, 0 - $this->maxLength);
+ }
+}
diff --git a/vendor/symfony/console/Question/ChoiceQuestion.php b/vendor/symfony/console/Question/ChoiceQuestion.php
new file mode 100644
index 00000000..c0df516e
--- /dev/null
+++ b/vendor/symfony/console/Question/ChoiceQuestion.php
@@ -0,0 +1,163 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Question;
+
+use ClassLeak202307\Symfony\Component\Console\Exception\InvalidArgumentException;
+/**
+ * Represents a choice question.
+ *
+ * @author Fabien Potencier
+ */
+class ChoiceQuestion extends Question
+{
+ /**
+ * @var mixed[]
+ */
+ private $choices;
+ /**
+ * @var bool
+ */
+ private $multiselect = \false;
+ /**
+ * @var string
+ */
+ private $prompt = ' > ';
+ /**
+ * @var string
+ */
+ private $errorMessage = 'Value "%s" is invalid';
+ /**
+ * @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(string $question, array $choices, $default = null)
+ {
+ if (!$choices) {
+ throw new \LogicException('Choice question must have at least 1 choice available.');
+ }
+ parent::__construct($question, $default);
+ $this->choices = $choices;
+ $this->setValidator($this->getDefaultValidator());
+ $this->setAutocompleterValues($choices);
+ }
+ /**
+ * Returns available choices.
+ */
+ public function getChoices() : array
+ {
+ return $this->choices;
+ }
+ /**
+ * Sets multiselect option.
+ *
+ * When multiselect is set to true, multiple choices can be answered.
+ *
+ * @return $this
+ */
+ public function setMultiselect(bool $multiselect)
+ {
+ $this->multiselect = $multiselect;
+ $this->setValidator($this->getDefaultValidator());
+ return $this;
+ }
+ /**
+ * Returns whether the choices are multiselect.
+ */
+ public function isMultiselect() : bool
+ {
+ return $this->multiselect;
+ }
+ /**
+ * Gets the prompt for choices.
+ */
+ public function getPrompt() : string
+ {
+ return $this->prompt;
+ }
+ /**
+ * Sets the prompt for choices.
+ *
+ * @return $this
+ */
+ public function setPrompt(string $prompt)
+ {
+ $this->prompt = $prompt;
+ return $this;
+ }
+ /**
+ * Sets the error message for invalid values.
+ *
+ * The error message has a string placeholder (%s) for the invalid value.
+ *
+ * @return $this
+ */
+ public function setErrorMessage(string $errorMessage)
+ {
+ $this->errorMessage = $errorMessage;
+ $this->setValidator($this->getDefaultValidator());
+ return $this;
+ }
+ private function getDefaultValidator() : callable
+ {
+ $choices = $this->choices;
+ $errorMessage = $this->errorMessage;
+ $multiselect = $this->multiselect;
+ $isAssoc = $this->isAssoc($choices);
+ return function ($selected) use($choices, $errorMessage, $multiselect, $isAssoc) {
+ if ($multiselect) {
+ // Check for a separated comma values
+ if (!\preg_match('/^[^,]+(?:,[^,]+)*$/', (string) $selected, $matches)) {
+ throw new InvalidArgumentException(\sprintf($errorMessage, $selected));
+ }
+ $selectedChoices = \explode(',', (string) $selected);
+ } else {
+ $selectedChoices = [$selected];
+ }
+ if ($this->isTrimmable()) {
+ foreach ($selectedChoices as $k => $v) {
+ $selectedChoices[$k] = \trim((string) $v);
+ }
+ }
+ $multiselectChoices = [];
+ foreach ($selectedChoices as $value) {
+ $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)));
+ }
+ $result = \array_search($value, $choices);
+ if (!$isAssoc) {
+ if (\false !== $result) {
+ $result = $choices[$result];
+ } elseif (isset($choices[$value])) {
+ $result = $choices[$value];
+ }
+ } elseif (\false === $result && isset($choices[$value])) {
+ $result = $value;
+ }
+ if (\false === $result) {
+ throw new InvalidArgumentException(\sprintf($errorMessage, $value));
+ }
+ // For associative choices, consistently return the key as string:
+ $multiselectChoices[] = $isAssoc ? (string) $result : $result;
+ }
+ if ($multiselect) {
+ return $multiselectChoices;
+ }
+ return \current($multiselectChoices);
+ };
+ }
+}
diff --git a/vendor/symfony/console/Question/ConfirmationQuestion.php b/vendor/symfony/console/Question/ConfirmationQuestion.php
new file mode 100644
index 00000000..d2266cb6
--- /dev/null
+++ b/vendor/symfony/console/Question/ConfirmationQuestion.php
@@ -0,0 +1,53 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Question;
+
+/**
+ * Represents a yes/no question.
+ *
+ * @author Fabien Potencier
+ */
+class ConfirmationQuestion extends Question
+{
+ /**
+ * @var string
+ */
+ private $trueAnswerRegex;
+ /**
+ * @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(string $question, bool $default = \true, string $trueAnswerRegex = '/^y/i')
+ {
+ parent::__construct($question, $default);
+ $this->trueAnswerRegex = $trueAnswerRegex;
+ $this->setNormalizer($this->getDefaultNormalizer());
+ }
+ /**
+ * Returns the default answer normalizer.
+ */
+ private function getDefaultNormalizer() : callable
+ {
+ $default = $this->getDefault();
+ $regex = $this->trueAnswerRegex;
+ return function ($answer) use($default, $regex) {
+ if (\is_bool($answer)) {
+ return $answer;
+ }
+ $answerIsTrue = (bool) \preg_match($regex, $answer);
+ if (\false === $default) {
+ return $answer && $answerIsTrue;
+ }
+ return '' === $answer || $answerIsTrue;
+ };
+ }
+}
diff --git a/vendor/symfony/console/Question/Question.php b/vendor/symfony/console/Question/Question.php
new file mode 100644
index 00000000..62ff6944
--- /dev/null
+++ b/vendor/symfony/console/Question/Question.php
@@ -0,0 +1,285 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Question;
+
+use ClassLeak202307\Symfony\Component\Console\Exception\InvalidArgumentException;
+use ClassLeak202307\Symfony\Component\Console\Exception\LogicException;
+/**
+ * Represents a Question.
+ *
+ * @author Fabien Potencier
+ */
+class Question
+{
+ /**
+ * @var string
+ */
+ private $question;
+ /**
+ * @var int|null
+ */
+ private $attempts;
+ /**
+ * @var bool
+ */
+ private $hidden = \false;
+ /**
+ * @var bool
+ */
+ private $hiddenFallback = \true;
+ /**
+ * @var \Closure|null
+ */
+ private $autocompleterCallback;
+ /**
+ * @var \Closure|null
+ */
+ private $validator;
+ /**
+ * @var string|int|bool|null|float
+ */
+ private $default;
+ /**
+ * @var \Closure|null
+ */
+ private $normalizer;
+ /**
+ * @var bool
+ */
+ private $trimmable = \true;
+ /**
+ * @var bool
+ */
+ private $multiline = \false;
+ /**
+ * @param string $question The question to ask to the user
+ * @param string|bool|int|float $default The default answer to return if the user enters nothing
+ */
+ public function __construct(string $question, $default = null)
+ {
+ $this->question = $question;
+ $this->default = $default;
+ }
+ /**
+ * Returns the question.
+ */
+ public function getQuestion() : string
+ {
+ return $this->question;
+ }
+ /**
+ * Returns the default answer.
+ * @return string|bool|int|float|null
+ */
+ public function getDefault()
+ {
+ return $this->default;
+ }
+ /**
+ * Returns whether the user response accepts newline characters.
+ */
+ public function isMultiline() : bool
+ {
+ return $this->multiline;
+ }
+ /**
+ * Sets whether the user response should accept newline characters.
+ *
+ * @return $this
+ */
+ public function setMultiline(bool $multiline)
+ {
+ $this->multiline = $multiline;
+ return $this;
+ }
+ /**
+ * Returns whether the user response must be hidden.
+ */
+ public function isHidden() : bool
+ {
+ return $this->hidden;
+ }
+ /**
+ * Sets whether the user response must be hidden or not.
+ *
+ * @return $this
+ *
+ * @throws LogicException In case the autocompleter is also used
+ */
+ public function setHidden(bool $hidden)
+ {
+ if ($this->autocompleterCallback) {
+ throw new LogicException('A hidden question cannot use the autocompleter.');
+ }
+ $this->hidden = $hidden;
+ return $this;
+ }
+ /**
+ * In case the response cannot be hidden, whether to fallback on non-hidden question or not.
+ */
+ public function isHiddenFallback() : bool
+ {
+ return $this->hiddenFallback;
+ }
+ /**
+ * Sets whether to fallback on non-hidden question if the response cannot be hidden.
+ *
+ * @return $this
+ */
+ public function setHiddenFallback(bool $fallback)
+ {
+ $this->hiddenFallback = $fallback;
+ return $this;
+ }
+ /**
+ * Gets values for the autocompleter.
+ */
+ public function getAutocompleterValues() : ?iterable
+ {
+ $callback = $this->getAutocompleterCallback();
+ return $callback ? $callback('') : null;
+ }
+ /**
+ * Sets values for the autocompleter.
+ *
+ * @return $this
+ *
+ * @throws LogicException
+ */
+ public function setAutocompleterValues(?iterable $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) {
+ $callback = static function () use($values) {
+ static $valueCache;
+ return $valueCache = $valueCache ?? \iterator_to_array($values, \false);
+ };
+ } else {
+ $callback = null;
+ }
+ return $this->setAutocompleterCallback($callback);
+ }
+ /**
+ * 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)
+ {
+ if (1 > \func_num_args()) {
+ trigger_deprecation('symfony/console', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
+ }
+ if ($this->hidden && null !== $callback) {
+ throw new LogicException('A hidden question cannot use the autocompleter.');
+ }
+ $this->autocompleterCallback = null === $callback ? null : \Closure::fromCallable($callback);
+ return $this;
+ }
+ /**
+ * Sets a validator for the question.
+ *
+ * @return $this
+ */
+ public function setValidator(callable $validator = null)
+ {
+ if (1 > \func_num_args()) {
+ trigger_deprecation('symfony/console', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
+ }
+ $this->validator = null === $validator ? null : \Closure::fromCallable($validator);
+ return $this;
+ }
+ /**
+ * Gets the validator for the question.
+ */
+ public function getValidator() : ?callable
+ {
+ return $this->validator;
+ }
+ /**
+ * Sets the maximum number of attempts.
+ *
+ * Null means an unlimited number of attempts.
+ *
+ * @return $this
+ *
+ * @throws InvalidArgumentException in case the number of attempts is invalid
+ */
+ public function setMaxAttempts(?int $attempts)
+ {
+ if (null !== $attempts && $attempts < 1) {
+ throw new InvalidArgumentException('Maximum number of attempts must be a positive value.');
+ }
+ $this->attempts = $attempts;
+ return $this;
+ }
+ /**
+ * Gets the maximum number of attempts.
+ *
+ * Null means an unlimited number of attempts.
+ */
+ public function getMaxAttempts() : ?int
+ {
+ return $this->attempts;
+ }
+ /**
+ * Sets a normalizer for the response.
+ *
+ * The normalizer can be a callable (a string), a closure or a class implementing __invoke.
+ *
+ * @return $this
+ */
+ public function setNormalizer(callable $normalizer)
+ {
+ $this->normalizer = \Closure::fromCallable($normalizer);
+ return $this;
+ }
+ /**
+ * Gets the normalizer for the response.
+ *
+ * The normalizer can ba a callable (a string), a closure or a class implementing __invoke.
+ */
+ public function getNormalizer() : ?callable
+ {
+ return $this->normalizer;
+ }
+ /**
+ * @return bool
+ */
+ protected function isAssoc(array $array)
+ {
+ return (bool) \count(\array_filter(\array_keys($array), 'is_string'));
+ }
+ public function isTrimmable() : bool
+ {
+ return $this->trimmable;
+ }
+ /**
+ * @return $this
+ */
+ public function setTrimmable(bool $trimmable)
+ {
+ $this->trimmable = $trimmable;
+ return $this;
+ }
+}
diff --git a/vendor/symfony/console/README.md b/vendor/symfony/console/README.md
new file mode 100644
index 00000000..bfd48810
--- /dev/null
+++ b/vendor/symfony/console/README.md
@@ -0,0 +1,36 @@
+Console Component
+=================
+
+The Console component eases the creation of beautiful and testable command line
+interfaces.
+
+Sponsor
+-------
+
+The Console component for Symfony 6.3 is [backed][1] by [Les-Tilleuls.coop][2].
+
+Les-Tilleuls.coop is a team of 70+ Symfony experts who can help you design, develop and
+fix your projects. They provide a wide range of professional services including development,
+consulting, coaching, training and audits. They also are highly skilled in JS, Go and DevOps.
+They are a worker cooperative!
+
+Help Symfony by [sponsoring][3] its development!
+
+Resources
+---------
+
+ * [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
diff --git a/vendor/symfony/console/Resources/bin/hiddeninput.exe b/vendor/symfony/console/Resources/bin/hiddeninput.exe
new file mode 100644
index 00000000..c8cf65e8
Binary files /dev/null and b/vendor/symfony/console/Resources/bin/hiddeninput.exe differ
diff --git a/vendor/symfony/console/Resources/completion.bash b/vendor/symfony/console/Resources/completion.bash
new file mode 100644
index 00000000..0d76eacc
--- /dev/null
+++ b/vendor/symfony/console/Resources/completion.bash
@@ -0,0 +1,94 @@
+# This file is part of the Symfony package.
+#
+# (c) Fabien Potencier
+#
+# For the full copyright and license information, please view
+# https://symfony.com/doc/current/contributing/code/license.html
+
+_sf_{{ COMMAND_NAME }}() {
+
+ # Use the default completion for shell redirect operators.
+ for w in '>' '>>' '&>' '<'; do
+ if [[ $w = "${COMP_WORDS[COMP_CWORD-1]}" ]]; then
+ compopt -o filenames
+ COMPREPLY=($(compgen -f -- "${COMP_WORDS[COMP_CWORD]}"))
+ return 0
+ fi
+ done
+
+ # 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" "-a{{ 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 }}
diff --git a/vendor/symfony/console/Resources/completion.fish b/vendor/symfony/console/Resources/completion.fish
new file mode 100644
index 00000000..1c34292a
--- /dev/null
+++ b/vendor/symfony/console/Resources/completion.fish
@@ -0,0 +1,29 @@
+# This file is part of the Symfony package.
+#
+# (c) Fabien Potencier
+#
+# For the full copyright and license information, please view
+# https://symfony.com/doc/current/contributing/code/license.html
+
+function _sf_{{ COMMAND_NAME }}
+ set sf_cmd (commandline -o)
+ set c (count (commandline -oc))
+
+ set completecmd "$sf_cmd[1]" "_complete" "--no-interaction" "-sfish" "-a{{ VERSION }}"
+
+ for i in $sf_cmd
+ if [ $i != "" ]
+ set completecmd $completecmd "-i$i"
+ end
+ end
+
+ set completecmd $completecmd "-c$c"
+
+ set sfcomplete ($completecmd)
+
+ for i in $sfcomplete
+ echo $i
+ end
+end
+
+complete -c '{{ COMMAND_NAME }}' -a '(_sf_{{ COMMAND_NAME }})' -f
diff --git a/vendor/symfony/console/Resources/completion.zsh b/vendor/symfony/console/Resources/completion.zsh
new file mode 100644
index 00000000..ff76fe5f
--- /dev/null
+++ b/vendor/symfony/console/Resources/completion.zsh
@@ -0,0 +1,82 @@
+#compdef {{ COMMAND_NAME }}
+
+# This file is part of the Symfony package.
+#
+# (c) Fabien Potencier
+#
+# For the full copyright and license information, please view
+# https://symfony.com/doc/current/contributing/code/license.html
+
+#
+# zsh completions for {{ COMMAND_NAME }}
+#
+# References:
+# - https://github.com/spf13/cobra/blob/master/zsh_completions.go
+# - https://github.com/symfony/symfony/blob/5.4/src/Symfony/Component/Console/Resources/completion.bash
+#
+_sf_{{ COMMAND_NAME }}() {
+ local lastParam flagPrefix requestComp out comp
+ local -a completions
+
+ # The user could have moved the cursor backwards on the command-line.
+ # We need to trigger completion from the $CURRENT location, so we need
+ # to truncate the command-line ($words) up to the $CURRENT location.
+ # (We cannot use $CURSOR as its value does not work when a command is an alias.)
+ words=("${=words[1,CURRENT]}") lastParam=${words[-1]}
+
+ # For zsh, when completing a flag with an = (e.g., {{ COMMAND_NAME }} -n=)
+ # completions must be prefixed with the flag
+ setopt local_options BASH_REMATCH
+ if [[ "${lastParam}" =~ '-.*=' ]]; then
+ # We are dealing with a flag with an =
+ flagPrefix="-P ${BASH_REMATCH}"
+ fi
+
+ # Prepare the command to obtain completions
+ requestComp="${words[0]} ${words[1]} _complete --no-interaction -szsh -a{{ VERSION }} -c$((CURRENT-1))" i=""
+ 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
+ i="${i}-i${w} "
+ fi
+ done
+
+ # Ensure at least 1 input
+ if [ "${i}" = "" ]; then
+ requestComp="${requestComp} -i\" \""
+ else
+ requestComp="${requestComp} ${i}"
+ fi
+
+ # Use eval to handle any environment variables and such
+ out=$(eval ${requestComp} 2>/dev/null)
+
+ while IFS='\n' read -r comp; do
+ if [ -n "$comp" ]; then
+ # If requested, completions are returned with a description.
+ # The description is preceded by a TAB character.
+ # For zsh's _describe, we need to use a : instead of a TAB.
+ # We first need to escape any : as part of the completion itself.
+ comp=${comp//:/\\:}
+ local tab=$(printf '\t')
+ comp=${comp//$tab/:}
+ completions+=${comp}
+ fi
+ done < <(printf "%s\n" "${out[@]}")
+
+ # Let inbuilt _describe handle completions
+ eval _describe "completions" completions $flagPrefix
+ return $?
+}
+
+compdef _sf_{{ COMMAND_NAME }} {{ COMMAND_NAME }}
diff --git a/vendor/symfony/console/SignalRegistry/SignalRegistry.php b/vendor/symfony/console/SignalRegistry/SignalRegistry.php
new file mode 100644
index 00000000..7b8c7334
--- /dev/null
+++ b/vendor/symfony/console/SignalRegistry/SignalRegistry.php
@@ -0,0 +1,51 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\SignalRegistry;
+
+final class SignalRegistry
+{
+ /**
+ * @var mixed[]
+ */
+ private $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, \Closure::fromCallable([$this, 'handle']));
+ }
+ public static function isSupported() : bool
+ {
+ return \function_exists('pcntl_signal');
+ }
+ /**
+ * @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);
+ }
+ }
+}
diff --git a/vendor/symfony/console/SingleCommandApplication.php b/vendor/symfony/console/SingleCommandApplication.php
new file mode 100644
index 00000000..99dfa17b
--- /dev/null
+++ b/vendor/symfony/console/SingleCommandApplication.php
@@ -0,0 +1,71 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console;
+
+use ClassLeak202307\Symfony\Component\Console\Command\Command;
+use ClassLeak202307\Symfony\Component\Console\Input\InputInterface;
+use ClassLeak202307\Symfony\Component\Console\Output\OutputInterface;
+/**
+ * @author Grégoire Pineau
+ */
+class SingleCommandApplication extends Command
+{
+ /**
+ * @var string
+ */
+ private $version = 'UNKNOWN';
+ /**
+ * @var bool
+ */
+ private $autoExit = \true;
+ /**
+ * @var bool
+ */
+ private $running = \false;
+ /**
+ * @return $this
+ */
+ public function setVersion(string $version)
+ {
+ $this->version = $version;
+ return $this;
+ }
+ /**
+ * @final
+ *
+ * @return $this
+ */
+ public function setAutoExit(bool $autoExit)
+ {
+ $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;
+ }
+}
diff --git a/vendor/symfony/console/Style/OutputStyle.php b/vendor/symfony/console/Style/OutputStyle.php
new file mode 100644
index 00000000..d97ac7bb
--- /dev/null
+++ b/vendor/symfony/console/Style/OutputStyle.php
@@ -0,0 +1,118 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Style;
+
+use ClassLeak202307\Symfony\Component\Console\Formatter\OutputFormatterInterface;
+use ClassLeak202307\Symfony\Component\Console\Helper\ProgressBar;
+use ClassLeak202307\Symfony\Component\Console\Output\ConsoleOutputInterface;
+use ClassLeak202307\Symfony\Component\Console\Output\OutputInterface;
+/**
+ * Decorates output to add console style guide helpers.
+ *
+ * @author Kevin Bond
+ */
+abstract class OutputStyle implements OutputInterface, StyleInterface
+{
+ /**
+ * @var \Symfony\Component\Console\Output\OutputInterface
+ */
+ private $output;
+ public function __construct(OutputInterface $output)
+ {
+ $this->output = $output;
+ }
+ /**
+ * @return void
+ */
+ public function newLine(int $count = 1)
+ {
+ $this->output->write(\str_repeat(\PHP_EOL, $count));
+ }
+ public function createProgressBar(int $max = 0) : ProgressBar
+ {
+ return new ProgressBar($this->output, $max);
+ }
+ /**
+ * @return void
+ * @param string|mixed[] $messages
+ */
+ public function write($messages, bool $newline = \false, int $type = self::OUTPUT_NORMAL)
+ {
+ $this->output->write($messages, $newline, $type);
+ }
+ /**
+ * @return void
+ * @param string|mixed[] $messages
+ */
+ public function writeln($messages, int $type = self::OUTPUT_NORMAL)
+ {
+ $this->output->writeln($messages, $type);
+ }
+ /**
+ * @return void
+ */
+ public function setVerbosity(int $level)
+ {
+ $this->output->setVerbosity($level);
+ }
+ public function getVerbosity() : int
+ {
+ return $this->output->getVerbosity();
+ }
+ /**
+ * @return void
+ */
+ public function setDecorated(bool $decorated)
+ {
+ $this->output->setDecorated($decorated);
+ }
+ public function isDecorated() : bool
+ {
+ return $this->output->isDecorated();
+ }
+ /**
+ * @return void
+ */
+ public function setFormatter(OutputFormatterInterface $formatter)
+ {
+ $this->output->setFormatter($formatter);
+ }
+ public function getFormatter() : OutputFormatterInterface
+ {
+ return $this->output->getFormatter();
+ }
+ public function isQuiet() : bool
+ {
+ return $this->output->isQuiet();
+ }
+ public function isVerbose() : bool
+ {
+ return $this->output->isVerbose();
+ }
+ public function isVeryVerbose() : bool
+ {
+ return $this->output->isVeryVerbose();
+ }
+ public function isDebug() : bool
+ {
+ return $this->output->isDebug();
+ }
+ /**
+ * @return OutputInterface
+ */
+ protected function getErrorOutput()
+ {
+ if (!$this->output instanceof ConsoleOutputInterface) {
+ return $this->output;
+ }
+ return $this->output->getErrorOutput();
+ }
+}
diff --git a/vendor/symfony/console/Style/StyleInterface.php b/vendor/symfony/console/Style/StyleInterface.php
new file mode 100644
index 00000000..0835a73a
--- /dev/null
+++ b/vendor/symfony/console/Style/StyleInterface.php
@@ -0,0 +1,130 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Style;
+
+/**
+ * Output style helpers.
+ *
+ * @author Kevin Bond
+ */
+interface StyleInterface
+{
+ /**
+ * Formats a command title.
+ *
+ * @return void
+ */
+ public function title(string $message);
+ /**
+ * Formats a section title.
+ *
+ * @return void
+ */
+ public function section(string $message);
+ /**
+ * Formats a list.
+ *
+ * @return void
+ */
+ public function listing(array $elements);
+ /**
+ * Formats informational text.
+ *
+ * @return void
+ * @param string|mixed[] $message
+ */
+ public function text($message);
+ /**
+ * Formats a success result bar.
+ *
+ * @return void
+ * @param string|mixed[] $message
+ */
+ public function success($message);
+ /**
+ * Formats an error result bar.
+ *
+ * @return void
+ * @param string|mixed[] $message
+ */
+ public function error($message);
+ /**
+ * Formats an warning result bar.
+ *
+ * @return void
+ * @param string|mixed[] $message
+ */
+ public function warning($message);
+ /**
+ * Formats a note admonition.
+ *
+ * @return void
+ * @param string|mixed[] $message
+ */
+ public function note($message);
+ /**
+ * Formats a caution admonition.
+ *
+ * @return void
+ * @param string|mixed[] $message
+ */
+ public function caution($message);
+ /**
+ * Formats a table.
+ *
+ * @return void
+ */
+ public function table(array $headers, array $rows);
+ /**
+ * Asks a question.
+ * @return mixed
+ */
+ public function ask(string $question, string $default = null, callable $validator = null);
+ /**
+ * Asks a question with the user input hidden.
+ * @return mixed
+ */
+ public function askHidden(string $question, callable $validator = null);
+ /**
+ * Asks for confirmation.
+ */
+ public function confirm(string $question, bool $default = \true) : bool;
+ /**
+ * Asks a choice question.
+ * @param mixed $default
+ * @return mixed
+ */
+ public function choice(string $question, array $choices, $default = null);
+ /**
+ * Add newline(s).
+ *
+ * @return void
+ */
+ public function newLine(int $count = 1);
+ /**
+ * Starts the progress output.
+ *
+ * @return void
+ */
+ public function progressStart(int $max = 0);
+ /**
+ * Advances the progress output X steps.
+ *
+ * @return void
+ */
+ public function progressAdvance(int $step = 1);
+ /**
+ * Finishes the progress output.
+ *
+ * @return void
+ */
+ public function progressFinish();
+}
diff --git a/vendor/symfony/console/Style/SymfonyStyle.php b/vendor/symfony/console/Style/SymfonyStyle.php
new file mode 100644
index 00000000..d1b6c721
--- /dev/null
+++ b/vendor/symfony/console/Style/SymfonyStyle.php
@@ -0,0 +1,462 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Style;
+
+use ClassLeak202307\Symfony\Component\Console\Exception\InvalidArgumentException;
+use ClassLeak202307\Symfony\Component\Console\Exception\RuntimeException;
+use ClassLeak202307\Symfony\Component\Console\Formatter\OutputFormatter;
+use ClassLeak202307\Symfony\Component\Console\Helper\Helper;
+use ClassLeak202307\Symfony\Component\Console\Helper\OutputWrapper;
+use ClassLeak202307\Symfony\Component\Console\Helper\ProgressBar;
+use ClassLeak202307\Symfony\Component\Console\Helper\SymfonyQuestionHelper;
+use ClassLeak202307\Symfony\Component\Console\Helper\Table;
+use ClassLeak202307\Symfony\Component\Console\Helper\TableCell;
+use ClassLeak202307\Symfony\Component\Console\Helper\TableSeparator;
+use ClassLeak202307\Symfony\Component\Console\Input\InputInterface;
+use ClassLeak202307\Symfony\Component\Console\Output\ConsoleOutputInterface;
+use ClassLeak202307\Symfony\Component\Console\Output\ConsoleSectionOutput;
+use ClassLeak202307\Symfony\Component\Console\Output\OutputInterface;
+use ClassLeak202307\Symfony\Component\Console\Output\TrimmedBufferOutput;
+use ClassLeak202307\Symfony\Component\Console\Question\ChoiceQuestion;
+use ClassLeak202307\Symfony\Component\Console\Question\ConfirmationQuestion;
+use ClassLeak202307\Symfony\Component\Console\Question\Question;
+use ClassLeak202307\Symfony\Component\Console\Terminal;
+/**
+ * Output decorator helpers for the Symfony Style Guide.
+ *
+ * @author Kevin Bond
+ */
+class SymfonyStyle extends OutputStyle
+{
+ public const MAX_LINE_LENGTH = 120;
+ /**
+ * @var \Symfony\Component\Console\Input\InputInterface
+ */
+ private $input;
+ /**
+ * @var \Symfony\Component\Console\Output\OutputInterface
+ */
+ private $output;
+ /**
+ * @var \Symfony\Component\Console\Helper\SymfonyQuestionHelper
+ */
+ private $questionHelper;
+ /**
+ * @var \Symfony\Component\Console\Helper\ProgressBar
+ */
+ private $progressBar;
+ /**
+ * @var int
+ */
+ private $lineLength;
+ /**
+ * @var \Symfony\Component\Console\Output\TrimmedBufferOutput
+ */
+ private $bufferedOutput;
+ public function __construct(InputInterface $input, OutputInterface $output)
+ {
+ $this->input = $input;
+ $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);
+ parent::__construct($this->output = $output);
+ }
+ /**
+ * Formats a message as a block of text.
+ *
+ * @return void
+ * @param string|mixed[] $messages
+ */
+ public function block($messages, string $type = null, string $style = null, string $prefix = ' ', bool $padding = \false, bool $escape = \true)
+ {
+ $messages = \is_array($messages) ? \array_values($messages) : [$messages];
+ $this->autoPrependBlock();
+ $this->writeln($this->createBlock($messages, $type, $style, $prefix, $padding, $escape));
+ $this->newLine();
+ }
+ /**
+ * @return void
+ */
+ public function title(string $message)
+ {
+ $this->autoPrependBlock();
+ $this->writeln([\sprintf('%s>', OutputFormatter::escapeTrailingBackslash($message)), \sprintf('%s>', \str_repeat('=', Helper::width(Helper::removeDecoration($this->getFormatter(), $message))))]);
+ $this->newLine();
+ }
+ /**
+ * @return void
+ */
+ public function section(string $message)
+ {
+ $this->autoPrependBlock();
+ $this->writeln([\sprintf('%s>', OutputFormatter::escapeTrailingBackslash($message)), \sprintf('%s>', \str_repeat('-', Helper::width(Helper::removeDecoration($this->getFormatter(), $message))))]);
+ $this->newLine();
+ }
+ /**
+ * @return void
+ */
+ public function listing(array $elements)
+ {
+ $this->autoPrependText();
+ $elements = \array_map(function ($element) {
+ return \sprintf(' * %s', $element);
+ }, $elements);
+ $this->writeln($elements);
+ $this->newLine();
+ }
+ /**
+ * @return void
+ * @param string|mixed[] $message
+ */
+ public function text($message)
+ {
+ $this->autoPrependText();
+ $messages = \is_array($message) ? \array_values($message) : [$message];
+ foreach ($messages as $message) {
+ $this->writeln(\sprintf(' %s', $message));
+ }
+ }
+ /**
+ * Formats a command comment.
+ *
+ * @return void
+ * @param string|mixed[] $message
+ */
+ public function comment($message)
+ {
+ $this->block($message, null, null, ' // >', \false, \false);
+ }
+ /**
+ * @return void
+ * @param string|mixed[] $message
+ */
+ public function success($message)
+ {
+ $this->block($message, 'OK', 'fg=black;bg=green', ' ', \true);
+ }
+ /**
+ * @return void
+ * @param string|mixed[] $message
+ */
+ public function error($message)
+ {
+ $this->block($message, 'ERROR', 'fg=white;bg=red', ' ', \true);
+ }
+ /**
+ * @return void
+ * @param string|mixed[] $message
+ */
+ public function warning($message)
+ {
+ $this->block($message, 'WARNING', 'fg=black;bg=yellow', ' ', \true);
+ }
+ /**
+ * @return void
+ * @param string|mixed[] $message
+ */
+ public function note($message)
+ {
+ $this->block($message, 'NOTE', 'fg=yellow', ' ! ');
+ }
+ /**
+ * Formats an info message.
+ *
+ * @return void
+ * @param string|mixed[] $message
+ */
+ public function info($message)
+ {
+ $this->block($message, 'INFO', 'fg=green', ' ', \true);
+ }
+ /**
+ * @return void
+ * @param string|mixed[] $message
+ */
+ public function caution($message)
+ {
+ $this->block($message, 'CAUTION', 'fg=white;bg=red', ' ! ', \true);
+ }
+ /**
+ * @return void
+ */
+ public function table(array $headers, array $rows)
+ {
+ $this->createTable()->setHeaders($headers)->setRows($rows)->render();
+ $this->newLine();
+ }
+ /**
+ * Formats a horizontal table.
+ *
+ * @return void
+ */
+ 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()
+ *
+ * @return void
+ * @param string|mixed[]|\Symfony\Component\Console\Helper\TableSeparator ...$list
+ */
+ public function definitionList(...$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]);
+ }
+ /**
+ * @return mixed
+ */
+ public function ask(string $question, string $default = null, callable $validator = null)
+ {
+ $question = new Question($question, $default);
+ $question->setValidator($validator);
+ return $this->askQuestion($question);
+ }
+ /**
+ * @return mixed
+ */
+ public function askHidden(string $question, callable $validator = null)
+ {
+ $question = new Question($question);
+ $question->setHidden(\true);
+ $question->setValidator($validator);
+ return $this->askQuestion($question);
+ }
+ public function confirm(string $question, bool $default = \true) : bool
+ {
+ return $this->askQuestion(new ConfirmationQuestion($question, $default));
+ }
+ /**
+ * @param mixed $default
+ * @return mixed
+ */
+ public function choice(string $question, array $choices, $default = null, bool $multiSelect = \false)
+ {
+ if (null !== $default) {
+ $values = \array_flip($choices);
+ $default = $values[$default] ?? $default;
+ }
+ $questionChoice = new ChoiceQuestion($question, $choices, $default);
+ $questionChoice->setMultiselect($multiSelect);
+ return $this->askQuestion($questionChoice);
+ }
+ /**
+ * @return void
+ */
+ public function progressStart(int $max = 0)
+ {
+ $this->progressBar = $this->createProgressBar($max);
+ $this->progressBar->start();
+ }
+ /**
+ * @return void
+ */
+ public function progressAdvance(int $step = 1)
+ {
+ $this->getProgressBar()->advance($step);
+ }
+ /**
+ * @return void
+ */
+ public function progressFinish()
+ {
+ $this->getProgressBar()->finish();
+ $this->newLine(2);
+ unset($this->progressBar);
+ }
+ public function createProgressBar(int $max = 0) : ProgressBar
+ {
+ $progressBar = parent::createProgressBar($max);
+ if ('\\' !== \DIRECTORY_SEPARATOR || 'Hyper' === \getenv('TERM_PROGRAM')) {
+ $progressBar->setEmptyBarCharacter('░');
+ // light shade character \u2591
+ $progressBar->setProgressCharacter('');
+ $progressBar->setBarCharacter('▓');
+ // dark shade character \u2593
+ }
+ return $progressBar;
+ }
+ /**
+ * @see ProgressBar::iterate()
+ */
+ public function progressIterate(iterable $iterable, int $max = null) : iterable
+ {
+ yield from $this->createProgressBar()->iterate($iterable, $max);
+ $this->newLine(2);
+ }
+ /**
+ * @return mixed
+ */
+ public function askQuestion(Question $question)
+ {
+ if ($this->input->isInteractive()) {
+ $this->autoPrependBlock();
+ }
+ $this->questionHelper = $this->questionHelper ?? new SymfonyQuestionHelper();
+ $answer = $this->questionHelper->ask($this->input, $this, $question);
+ if ($this->input->isInteractive()) {
+ if ($this->output instanceof ConsoleSectionOutput) {
+ // add the new line of the `return` to submit the input to ConsoleSectionOutput, because ConsoleSectionOutput is holding all it's lines.
+ // this is relevant when a `ConsoleSectionOutput::clear` is called.
+ $this->output->addNewLineOfInputSubmit();
+ }
+ $this->newLine();
+ $this->bufferedOutput->write("\n");
+ }
+ return $answer;
+ }
+ /**
+ * @return void
+ * @param string|mixed[] $messages
+ */
+ public function writeln($messages, int $type = self::OUTPUT_NORMAL)
+ {
+ if (!\is_iterable($messages)) {
+ $messages = [$messages];
+ }
+ foreach ($messages as $message) {
+ parent::writeln($message, $type);
+ $this->writeBuffer($message, \true, $type);
+ }
+ }
+ /**
+ * @return void
+ * @param string|mixed[] $messages
+ */
+ public function write($messages, bool $newline = \false, int $type = self::OUTPUT_NORMAL)
+ {
+ if (!\is_iterable($messages)) {
+ $messages = [$messages];
+ }
+ foreach ($messages as $message) {
+ parent::write($message, $newline, $type);
+ $this->writeBuffer($message, $newline, $type);
+ }
+ }
+ /**
+ * @return void
+ */
+ public function newLine(int $count = 1)
+ {
+ parent::newLine($count);
+ $this->bufferedOutput->write(\str_repeat("\n", $count));
+ }
+ /**
+ * Returns a new instance which makes use of stderr if available.
+ */
+ public function getErrorStyle() : self
+ {
+ return new self($this->input, $this->getErrorOutput());
+ }
+ public function createTable() : Table
+ {
+ $output = $this->output instanceof ConsoleOutputInterface ? $this->output->section() : $this->output;
+ $style = clone Table::getStyleDefinition('symfony-style-guide');
+ $style->setCellHeaderFormat('%s');
+ return (new Table($output))->setStyle($style);
+ }
+ private function getProgressBar() : ProgressBar
+ {
+ if (!isset($this->progressBar)) {
+ throw new RuntimeException('The ProgressBar is not started.');
+ }
+ return $this->progressBar;
+ }
+ private function autoPrependBlock() : void
+ {
+ $chars = \substr(\str_replace(\PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2);
+ if (!isset($chars[0])) {
+ $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)
+ $this->newLine(2 - \substr_count($chars, "\n"));
+ }
+ private function autoPrependText() : void
+ {
+ $fetched = $this->bufferedOutput->fetch();
+ // Prepend new line if last char isn't EOL:
+ if ($fetched && \substr_compare($fetched, "\n", -\strlen("\n")) !== 0) {
+ $this->newLine();
+ }
+ }
+ private function writeBuffer(string $message, bool $newLine, int $type) : void
+ {
+ // We need to know if the last chars are PHP_EOL
+ $this->bufferedOutput->write($message, $newLine, $type);
+ }
+ private function createBlock(iterable $messages, string $type = null, string $style = null, string $prefix = ' ', bool $padding = \false, bool $escape = \false) : array
+ {
+ $indentLength = 0;
+ $prefixLength = Helper::width(Helper::removeDecoration($this->getFormatter(), $prefix));
+ $lines = [];
+ if (null !== $type) {
+ $type = \sprintf('[%s] ', $type);
+ $indentLength = Helper::width($type);
+ $lineIndentation = \str_repeat(' ', $indentLength);
+ }
+ // wrap and add newlines for each element
+ $outputWrapper = new OutputWrapper();
+ foreach ($messages as $key => $message) {
+ if ($escape) {
+ $message = OutputFormatter::escape($message);
+ }
+ $lines = \array_merge($lines, \explode(\PHP_EOL, $outputWrapper->wrap($message, $this->lineLength - $prefixLength - $indentLength, \PHP_EOL)));
+ if (\count($messages) > 1 && $key < \count($messages) - 1) {
+ $lines[] = '';
+ }
+ }
+ $firstLineIndex = 0;
+ if ($padding && $this->isDecorated()) {
+ $firstLineIndex = 1;
+ \array_unshift($lines, '');
+ $lines[] = '';
+ }
+ foreach ($lines as $i => &$line) {
+ if (null !== $type) {
+ $line = $firstLineIndex === $i ? $type . $line : $lineIndentation . $line;
+ }
+ $line = $prefix . $line;
+ $line .= \str_repeat(' ', \max($this->lineLength - Helper::width(Helper::removeDecoration($this->getFormatter(), $line)), 0));
+ if ($style) {
+ $line = \sprintf('<%s>%s>', $style, $line);
+ }
+ }
+ return $lines;
+ }
+}
diff --git a/vendor/symfony/console/Terminal.php b/vendor/symfony/console/Terminal.php
new file mode 100644
index 00000000..aa1a2178
--- /dev/null
+++ b/vendor/symfony/console/Terminal.php
@@ -0,0 +1,209 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console;
+
+use ClassLeak202307\Symfony\Component\Console\Output\AnsiColorMode;
+class Terminal
+{
+ public const DEFAULT_COLOR_MODE = AnsiColorMode::Ansi4;
+ /**
+ * @var \Symfony\Component\Console\Output\AnsiColorMode|null
+ */
+ private static $colorMode;
+ /**
+ * @var int|null
+ */
+ private static $width;
+ /**
+ * @var int|null
+ */
+ private static $height;
+ /**
+ * @var bool|null
+ */
+ private static $stty;
+ /**
+ * About Ansi color types: https://en.wikipedia.org/wiki/ANSI_escape_code#Colors
+ * For more information about true color support with terminals https://github.com/termstandard/colors/.
+ */
+ public static function getColorMode() : AnsiColorMode
+ {
+ // Use Cache from previous run (or user forced mode)
+ if (null !== self::$colorMode) {
+ return self::$colorMode;
+ }
+ // Try with $COLORTERM first
+ if (\is_string($colorterm = \getenv('COLORTERM'))) {
+ $colorterm = \strtolower($colorterm);
+ if (\strpos($colorterm, 'truecolor') !== \false) {
+ self::setColorMode(AnsiColorMode::Ansi24);
+ return self::$colorMode;
+ }
+ if (\strpos($colorterm, '256color') !== \false) {
+ self::setColorMode(AnsiColorMode::Ansi8);
+ return self::$colorMode;
+ }
+ }
+ // Try with $TERM
+ if (\is_string($term = \getenv('TERM'))) {
+ $term = \strtolower($term);
+ if (\strpos($term, 'truecolor') !== \false) {
+ self::setColorMode(AnsiColorMode::Ansi24);
+ return self::$colorMode;
+ }
+ if (\strpos($term, '256color') !== \false) {
+ self::setColorMode(AnsiColorMode::Ansi8);
+ return self::$colorMode;
+ }
+ }
+ self::setColorMode(self::DEFAULT_COLOR_MODE);
+ return self::$colorMode;
+ }
+ /**
+ * Force a terminal color mode rendering.
+ * @param ?\Symfony\Component\Console\Output\AnsiColorMode::* $colorMode
+ */
+ public static function setColorMode($colorMode) : void
+ {
+ self::$colorMode = $colorMode;
+ }
+ /**
+ * Gets the terminal width.
+ */
+ public function getWidth() : int
+ {
+ $width = \getenv('COLUMNS');
+ if (\false !== $width) {
+ return (int) \trim($width);
+ }
+ if (null === self::$width) {
+ self::initDimensions();
+ }
+ return self::$width ?: 80;
+ }
+ /**
+ * Gets the terminal height.
+ */
+ public function getHeight() : int
+ {
+ $height = \getenv('LINES');
+ if (\false !== $height) {
+ return (int) \trim($height);
+ }
+ if (null === self::$height) {
+ self::initDimensions();
+ }
+ return self::$height ?: 50;
+ }
+ /**
+ * @internal
+ */
+ public static function hasSttyAvailable() : bool
+ {
+ if (null !== self::$stty) {
+ return self::$stty;
+ }
+ // skip check if shell_exec function is disabled
+ if (!\function_exists('shell_exec')) {
+ return \false;
+ }
+ return self::$stty = (bool) \shell_exec('stty 2> ' . ('\\' === \DIRECTORY_SEPARATOR ? 'NUL' : '/dev/null'));
+ }
+ private static function initDimensions() : void
+ {
+ if ('\\' === \DIRECTORY_SEPARATOR) {
+ $ansicon = \getenv('ANSICON');
+ if (\false !== $ansicon && \preg_match('/^(\\d+)x(\\d+)(?: \\((\\d+)x(\\d+)\\))?$/', \trim($ansicon), $matches)) {
+ // extract [w, H] from "wxh (WxH)"
+ // or [w, h] from "wxh"
+ self::$width = (int) $matches[1];
+ self::$height = isset($matches[4]) ? (int) $matches[4] : (int) $matches[2];
+ } elseif (!self::hasVt100Support() && self::hasSttyAvailable()) {
+ // only use stty on Windows if the terminal does not support vt100 (e.g. Windows 7 + git-bash)
+ // testing for stty in a Windows 10 vt100-enabled console will implicitly disable vt100 support on STDOUT
+ self::initDimensionsUsingStty();
+ } elseif (null !== ($dimensions = self::getConsoleMode())) {
+ // extract [w, h] from "wxh"
+ self::$width = (int) $dimensions[0];
+ self::$height = (int) $dimensions[1];
+ }
+ } else {
+ self::initDimensionsUsingStty();
+ }
+ }
+ /**
+ * Returns whether STDOUT has vt100 support (some Windows 10+ configurations).
+ */
+ private static function hasVt100Support() : bool
+ {
+ return \function_exists('sapi_windows_vt100_support') && \sapi_windows_vt100_support(\fopen('php://stdout', 'w'));
+ }
+ /**
+ * Initializes dimensions using the output of an stty columns line.
+ */
+ private static function initDimensionsUsingStty() : void
+ {
+ if ($sttyString = self::getSttyColumns()) {
+ if (\preg_match('/rows.(\\d+);.columns.(\\d+);/is', $sttyString, $matches)) {
+ // extract [w, h] from "rows h; columns w;"
+ self::$width = (int) $matches[2];
+ self::$height = (int) $matches[1];
+ } elseif (\preg_match('/;.(\\d+).rows;.(\\d+).columns/is', $sttyString, $matches)) {
+ // extract [w, h] from "; h rows; w columns"
+ self::$width = (int) $matches[2];
+ self::$height = (int) $matches[1];
+ }
+ }
+ }
+ /**
+ * Runs and parses mode CON if it's available, suppressing any error output.
+ *
+ * @return int[]|null An array composed of the width and the height or null if it could not be parsed
+ */
+ private static function getConsoleMode() : ?array
+ {
+ $info = self::readFromProcess('mode CON');
+ if (null === $info || !\preg_match('/--------+\\r?\\n.+?(\\d+)\\r?\\n.+?(\\d+)\\r?\\n/', $info, $matches)) {
+ return null;
+ }
+ return [(int) $matches[2], (int) $matches[1]];
+ }
+ /**
+ * Runs and parses stty -a if it's available, suppressing any error output.
+ */
+ private static function getSttyColumns() : ?string
+ {
+ return self::readFromProcess(['stty', '-a']);
+ }
+ /**
+ * @param string|mixed[] $command
+ */
+ private static function readFromProcess($command) : ?string
+ {
+ if (!\function_exists('proc_open')) {
+ return null;
+ }
+ $descriptorspec = [1 => ['pipe', 'w'], 2 => ['pipe', 'w']];
+ $cp = \function_exists('sapi_windows_cp_set') ? \sapi_windows_cp_get() : 0;
+ $process = \proc_open(\is_array($command) ? \implode(' ', $command) : $command, $descriptorspec, $pipes, null, null, ['suppress_errors' => \true]);
+ if (!\is_resource($process)) {
+ return null;
+ }
+ $info = \stream_get_contents($pipes[1]);
+ \fclose($pipes[1]);
+ \fclose($pipes[2]);
+ \proc_close($process);
+ if ($cp) {
+ \sapi_windows_cp_set($cp);
+ }
+ return $info;
+ }
+}
diff --git a/vendor/symfony/console/Tester/ApplicationTester.php b/vendor/symfony/console/Tester/ApplicationTester.php
new file mode 100644
index 00000000..f07bd365
--- /dev/null
+++ b/vendor/symfony/console/Tester/ApplicationTester.php
@@ -0,0 +1,79 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Tester;
+
+use ClassLeak202307\Symfony\Component\Console\Application;
+use ClassLeak202307\Symfony\Component\Console\Input\ArrayInput;
+/**
+ * Eases the testing of console applications.
+ *
+ * When testing an application, don't forget to disable the auto exit flag:
+ *
+ * $application = new Application();
+ * $application->setAutoExit(false);
+ *
+ * @author Fabien Potencier
+ */
+class ApplicationTester
+{
+ use TesterTrait;
+ /**
+ * @var \Symfony\Component\Console\Application
+ */
+ private $application;
+ public function __construct(Application $application)
+ {
+ $this->application = $application;
+ }
+ /**
+ * Executes the application.
+ *
+ * Available options:
+ *
+ * * interactive: Sets the input interactive flag
+ * * decorated: Sets the output decorated flag
+ * * verbosity: Sets the output verbosity flag
+ * * capture_stderr_separately: Make output of stdOut and stdErr separately available
+ *
+ * @return int The command exit code
+ */
+ public function run(array $input, array $options = []) : int
+ {
+ $prevShellVerbosity = \getenv('SHELL_VERBOSITY');
+ try {
+ $this->input = new ArrayInput($input);
+ if (isset($options['interactive'])) {
+ $this->input->setInteractive($options['interactive']);
+ }
+ if ($this->inputs) {
+ $this->input->setStream(self::createStream($this->inputs));
+ }
+ $this->initOutput($options);
+ return $this->statusCode = $this->application->run($this->input, $this->output);
+ } finally {
+ // SHELL_VERBOSITY is set by Application::configureIO so we need to unset/reset it
+ // to its previous value to avoid one test's verbosity to spread to the following tests
+ if (\false === $prevShellVerbosity) {
+ if (\function_exists('putenv')) {
+ @\putenv('SHELL_VERBOSITY');
+ }
+ unset($_ENV['SHELL_VERBOSITY']);
+ unset($_SERVER['SHELL_VERBOSITY']);
+ } else {
+ if (\function_exists('putenv')) {
+ @\putenv('SHELL_VERBOSITY=' . $prevShellVerbosity);
+ }
+ $_ENV['SHELL_VERBOSITY'] = $prevShellVerbosity;
+ $_SERVER['SHELL_VERBOSITY'] = $prevShellVerbosity;
+ }
+ }
+ }
+}
diff --git a/vendor/symfony/console/Tester/CommandCompletionTester.php b/vendor/symfony/console/Tester/CommandCompletionTester.php
new file mode 100644
index 00000000..14fdab77
--- /dev/null
+++ b/vendor/symfony/console/Tester/CommandCompletionTester.php
@@ -0,0 +1,48 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Tester;
+
+use ClassLeak202307\Symfony\Component\Console\Command\Command;
+use ClassLeak202307\Symfony\Component\Console\Completion\CompletionInput;
+use ClassLeak202307\Symfony\Component\Console\Completion\CompletionSuggestions;
+/**
+ * Eases the testing of command completion.
+ *
+ * @author Jérôme Tamarelle
+ */
+class CommandCompletionTester
+{
+ private $command;
+ public function __construct(Command $command)
+ {
+ $this->command = $command;
+ }
+ /**
+ * Create completion suggestions from input tokens.
+ */
+ public function complete(array $input) : array
+ {
+ $currentIndex = \count($input);
+ if ('' === \end($input)) {
+ \array_pop($input);
+ }
+ \array_unshift($input, $this->command->getName());
+ $completionInput = CompletionInput::fromTokens($input, $currentIndex);
+ $completionInput->bind($this->command->getDefinition());
+ $suggestions = new CompletionSuggestions();
+ $this->command->complete($completionInput, $suggestions);
+ $options = [];
+ foreach ($suggestions->getOptionSuggestions() as $option) {
+ $options[] = '--' . $option->getName();
+ }
+ return \array_map('strval', \array_merge($options, $suggestions->getValueSuggestions()));
+ }
+}
diff --git a/vendor/symfony/console/Tester/CommandTester.php b/vendor/symfony/console/Tester/CommandTester.php
new file mode 100644
index 00000000..421cf479
--- /dev/null
+++ b/vendor/symfony/console/Tester/CommandTester.php
@@ -0,0 +1,66 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Tester;
+
+use ClassLeak202307\Symfony\Component\Console\Command\Command;
+use ClassLeak202307\Symfony\Component\Console\Input\ArrayInput;
+/**
+ * Eases the testing of console commands.
+ *
+ * @author Fabien Potencier
+ * @author Robin Chalas
+ */
+class CommandTester
+{
+ use TesterTrait;
+ /**
+ * @var \Symfony\Component\Console\Command\Command
+ */
+ private $command;
+ public function __construct(Command $command)
+ {
+ $this->command = $command;
+ }
+ /**
+ * Executes the command.
+ *
+ * Available execution options:
+ *
+ * * interactive: Sets the input interactive flag
+ * * decorated: Sets the output decorated flag
+ * * verbosity: Sets the output verbosity flag
+ * * capture_stderr_separately: Make output of stdOut and stdErr separately available
+ *
+ * @param array $input An array of command arguments and options
+ * @param array $options An array of execution options
+ *
+ * @return int The command exit code
+ */
+ public function execute(array $input, array $options = []) : int
+ {
+ // set the command name automatically if the application requires
+ // this argument and no command name was passed
+ if (!isset($input['command']) && null !== ($application = $this->command->getApplication()) && $application->getDefinition()->hasArgument('command')) {
+ $input = \array_merge(['command' => $this->command->getName()], $input);
+ }
+ $this->input = new ArrayInput($input);
+ // Use an in-memory input stream even if no inputs are set so that QuestionHelper::ask() does not rely on the blocking STDIN.
+ $this->input->setStream(self::createStream($this->inputs));
+ if (isset($options['interactive'])) {
+ $this->input->setInteractive($options['interactive']);
+ }
+ if (!isset($options['decorated'])) {
+ $options['decorated'] = \false;
+ }
+ $this->initOutput($options);
+ return $this->statusCode = $this->command->run($this->input, $this->output);
+ }
+}
diff --git a/vendor/symfony/console/Tester/Constraint/CommandIsSuccessful.php b/vendor/symfony/console/Tester/Constraint/CommandIsSuccessful.php
new file mode 100644
index 00000000..ee518102
--- /dev/null
+++ b/vendor/symfony/console/Tester/Constraint/CommandIsSuccessful.php
@@ -0,0 +1,34 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Tester\Constraint;
+
+use ClassLeak202307\PHPUnit\Framework\Constraint\Constraint;
+use ClassLeak202307\Symfony\Component\Console\Command\Command;
+final class CommandIsSuccessful extends Constraint
+{
+ public function toString() : string
+ {
+ return 'is successful';
+ }
+ protected function matches($other) : bool
+ {
+ return Command::SUCCESS === $other;
+ }
+ protected function failureDescription($other) : string
+ {
+ return 'the command ' . $this->toString();
+ }
+ protected function additionalFailureDescription($other) : string
+ {
+ $mapping = [Command::FAILURE => 'Command failed.', Command::INVALID => 'Command was invalid.'];
+ return $mapping[$other] ?? \sprintf('Command returned exit status %d.', $other);
+ }
+}
diff --git a/vendor/symfony/console/Tester/TesterTrait.php b/vendor/symfony/console/Tester/TesterTrait.php
new file mode 100644
index 00000000..d7516876
--- /dev/null
+++ b/vendor/symfony/console/Tester/TesterTrait.php
@@ -0,0 +1,167 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\Console\Tester;
+
+use ClassLeak202307\PHPUnit\Framework\Assert;
+use ClassLeak202307\Symfony\Component\Console\Input\InputInterface;
+use ClassLeak202307\Symfony\Component\Console\Output\ConsoleOutput;
+use ClassLeak202307\Symfony\Component\Console\Output\OutputInterface;
+use ClassLeak202307\Symfony\Component\Console\Output\StreamOutput;
+use ClassLeak202307\Symfony\Component\Console\Tester\Constraint\CommandIsSuccessful;
+/**
+ * @author Amrouche Hamza
+ */
+trait TesterTrait
+{
+ /**
+ * @var \Symfony\Component\Console\Output\StreamOutput
+ */
+ private $output;
+ /**
+ * @var mixed[]
+ */
+ private $inputs = [];
+ /**
+ * @var bool
+ */
+ private $captureStreamsIndependently = \false;
+ /**
+ * @var \Symfony\Component\Console\Input\InputInterface
+ */
+ private $input;
+ /**
+ * @var int
+ */
+ private $statusCode;
+ /**
+ * Gets the display returned by the last execution of the command or application.
+ *
+ * @throws \RuntimeException If it's called before the execute method
+ */
+ public function getDisplay(bool $normalize = \false) : string
+ {
+ if (!isset($this->output)) {
+ throw new \RuntimeException('Output not initialized, did you execute the command before requesting the display?');
+ }
+ \rewind($this->output->getStream());
+ $display = \stream_get_contents($this->output->getStream());
+ if ($normalize) {
+ $display = \str_replace(\PHP_EOL, "\n", $display);
+ }
+ return $display;
+ }
+ /**
+ * Gets the output written to STDERR by the application.
+ *
+ * @param bool $normalize Whether to normalize end of lines to \n or not
+ */
+ public function getErrorOutput(bool $normalize = \false) : string
+ {
+ if (!$this->captureStreamsIndependently) {
+ throw new \LogicException('The error output is not available when the tester is run without "capture_stderr_separately" option set.');
+ }
+ \rewind($this->output->getErrorOutput()->getStream());
+ $display = \stream_get_contents($this->output->getErrorOutput()->getStream());
+ if ($normalize) {
+ $display = \str_replace(\PHP_EOL, "\n", $display);
+ }
+ return $display;
+ }
+ /**
+ * Gets the input instance used by the last execution of the command or application.
+ */
+ public function getInput() : InputInterface
+ {
+ return $this->input;
+ }
+ /**
+ * Gets the output instance used by the last execution of the command or application.
+ */
+ public function getOutput() : OutputInterface
+ {
+ return $this->output;
+ }
+ /**
+ * Gets the status code returned by the last execution of the command or application.
+ *
+ * @throws \RuntimeException If it's called before the execute method
+ */
+ public function getStatusCode() : int
+ {
+ if (!isset($this->statusCode)) {
+ throw new \RuntimeException('Status code not initialized, did you execute the command before requesting the status code?');
+ }
+ return $this->statusCode;
+ }
+ public function assertCommandIsSuccessful(string $message = '') : void
+ {
+ Assert::assertThat($this->statusCode, new CommandIsSuccessful(), $message);
+ }
+ /**
+ * Sets the user inputs.
+ *
+ * @param array $inputs An array of strings representing each input
+ * passed to the command input stream
+ *
+ * @return $this
+ */
+ public function setInputs(array $inputs)
+ {
+ $this->inputs = $inputs;
+ return $this;
+ }
+ /**
+ * Initializes the output property.
+ *
+ * Available options:
+ *
+ * * decorated: Sets the output decorated flag
+ * * verbosity: Sets the output verbosity flag
+ * * capture_stderr_separately: Make output of stdOut and stdErr separately available
+ */
+ private function initOutput(array $options) : void
+ {
+ $this->captureStreamsIndependently = \array_key_exists('capture_stderr_separately', $options) && $options['capture_stderr_separately'];
+ if (!$this->captureStreamsIndependently) {
+ $this->output = new StreamOutput(\fopen('php://memory', 'w', \false));
+ if (isset($options['decorated'])) {
+ $this->output->setDecorated($options['decorated']);
+ }
+ if (isset($options['verbosity'])) {
+ $this->output->setVerbosity($options['verbosity']);
+ }
+ } else {
+ $this->output = new ConsoleOutput($options['verbosity'] ?? ConsoleOutput::VERBOSITY_NORMAL, $options['decorated'] ?? null);
+ $errorOutput = new StreamOutput(\fopen('php://memory', 'w', \false));
+ $errorOutput->setFormatter($this->output->getFormatter());
+ $errorOutput->setVerbosity($this->output->getVerbosity());
+ $errorOutput->setDecorated($this->output->isDecorated());
+ $reflectedOutput = new \ReflectionObject($this->output);
+ $strErrProperty = $reflectedOutput->getProperty('stderr');
+ $strErrProperty->setValue($this->output, $errorOutput);
+ $reflectedParent = $reflectedOutput->getParentClass();
+ $streamProperty = $reflectedParent->getProperty('stream');
+ $streamProperty->setValue($this->output, \fopen('php://memory', 'w', \false));
+ }
+ }
+ /**
+ * @return resource
+ */
+ private static function createStream(array $inputs)
+ {
+ $stream = \fopen('php://memory', 'r+', \false);
+ foreach ($inputs as $input) {
+ \fwrite($stream, $input . \PHP_EOL);
+ }
+ \rewind($stream);
+ return $stream;
+ }
+}
diff --git a/vendor/symfony/console/composer.json b/vendor/symfony/console/composer.json
new file mode 100644
index 00000000..59dea6da
--- /dev/null
+++ b/vendor/symfony/console/composer.json
@@ -0,0 +1,58 @@
+{
+ "name": "symfony\/console",
+ "type": "library",
+ "description": "Eases the creation of beautiful and testable command line interfaces",
+ "keywords": [
+ "console",
+ "cli",
+ "command-line",
+ "terminal"
+ ],
+ "homepage": "https:\/\/symfony.com",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https:\/\/symfony.com\/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=8.1",
+ "symfony\/deprecation-contracts": "^2.5|^3",
+ "symfony\/polyfill-mbstring": "~1.0",
+ "symfony\/service-contracts": "^2.5|^3",
+ "symfony\/string": "^5.4|^6.0"
+ },
+ "require-dev": {
+ "symfony\/config": "^5.4|^6.0",
+ "symfony\/event-dispatcher": "^5.4|^6.0",
+ "symfony\/dependency-injection": "^5.4|^6.0",
+ "symfony\/lock": "^5.4|^6.0",
+ "symfony\/process": "^5.4|^6.0",
+ "symfony\/var-dumper": "^5.4|^6.0",
+ "psr\/log": "^1|^2|^3"
+ },
+ "provide": {
+ "psr\/log-implementation": "1.0|2.0|3.0"
+ },
+ "conflict": {
+ "symfony\/dependency-injection": "<5.4",
+ "symfony\/dotenv": "<5.4",
+ "symfony\/event-dispatcher": "<5.4",
+ "symfony\/lock": "<5.4",
+ "symfony\/process": "<5.4"
+ },
+ "autoload": {
+ "psr-4": {
+ "ClassLeak202307\\Symfony\\Component\\Console\\": ""
+ },
+ "exclude-from-classmap": [
+ "\/Tests\/"
+ ]
+ },
+ "minimum-stability": "dev"
+}
\ No newline at end of file
diff --git a/vendor/symfony/deprecation-contracts/CHANGELOG.md b/vendor/symfony/deprecation-contracts/CHANGELOG.md
new file mode 100644
index 00000000..7932e261
--- /dev/null
+++ b/vendor/symfony/deprecation-contracts/CHANGELOG.md
@@ -0,0 +1,5 @@
+CHANGELOG
+=========
+
+The changelog is maintained for all Symfony contracts at the following URL:
+https://github.com/symfony/contracts/blob/main/CHANGELOG.md
diff --git a/vendor/symfony/deprecation-contracts/LICENSE b/vendor/symfony/deprecation-contracts/LICENSE
new file mode 100644
index 00000000..0ed3a246
--- /dev/null
+++ b/vendor/symfony/deprecation-contracts/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2020-present 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
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/symfony/deprecation-contracts/README.md b/vendor/symfony/deprecation-contracts/README.md
new file mode 100644
index 00000000..9814864c
--- /dev/null
+++ b/vendor/symfony/deprecation-contracts/README.md
@@ -0,0 +1,26 @@
+Symfony Deprecation Contracts
+=============================
+
+A generic function and convention to trigger deprecation notices.
+
+This package provides a single global function named `trigger_deprecation()` that triggers silenced deprecation notices.
+
+By using a custom PHP error handler such as the one provided by the Symfony ErrorHandler component,
+the triggered deprecations can be caught and logged for later discovery, both on dev and prod environments.
+
+The function requires at least 3 arguments:
+ - the name of the Composer package that is triggering the deprecation
+ - the version of the package that introduced the deprecation
+ - the message of the deprecation
+ - more arguments can be provided: they will be inserted in the message using `printf()` formatting
+
+Example:
+```php
+trigger_deprecation('symfony/blockchain', '8.9', 'Using "%s" is deprecated, use "%s" instead.', 'bitcoin', 'fabcoin');
+```
+
+This will generate the following message:
+`Since symfony/blockchain 8.9: Using "bitcoin" is deprecated, use "fabcoin" instead.`
+
+While not recommended, the deprecation notices can be completely ignored by declaring an empty
+`function trigger_deprecation() {}` in your application.
diff --git a/vendor/symfony/deprecation-contracts/composer.json b/vendor/symfony/deprecation-contracts/composer.json
new file mode 100644
index 00000000..768470a9
--- /dev/null
+++ b/vendor/symfony/deprecation-contracts/composer.json
@@ -0,0 +1,35 @@
+{
+ "name": "symfony\/deprecation-contracts",
+ "type": "library",
+ "description": "A generic function and convention to trigger deprecation notices",
+ "homepage": "https:\/\/symfony.com",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https:\/\/symfony.com\/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=8.1"
+ },
+ "autoload": {
+ "files": [
+ "function.php"
+ ]
+ },
+ "minimum-stability": "dev",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.4-dev"
+ },
+ "thanks": {
+ "name": "symfony\/contracts",
+ "url": "https:\/\/github.com\/symfony\/contracts"
+ }
+ }
+}
\ No newline at end of file
diff --git a/vendor/symfony/deprecation-contracts/function.php b/vendor/symfony/deprecation-contracts/function.php
new file mode 100644
index 00000000..d4371504
--- /dev/null
+++ b/vendor/symfony/deprecation-contracts/function.php
@@ -0,0 +1,27 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+if (!function_exists('trigger_deprecation')) {
+ /**
+ * Triggers a silenced deprecation notice.
+ *
+ * @param string $package The name of the Composer package that is triggering the deprecation
+ * @param string $version The version of the package that introduced the deprecation
+ * @param string $message The message of the deprecation
+ * @param mixed ...$args Values to insert in the message using printf() formatting
+ *
+ * @author Nicolas Grekas
+ */
+ function trigger_deprecation(string $package, string $version, string $message, ...$args): void
+ {
+ @trigger_error(($package || $version ? "Since $package $version: " : '').($args ? vsprintf($message, $args) : $message), \E_USER_DEPRECATED);
+ }
+}
diff --git a/vendor/symfony/service-contracts/Attribute/Required.php b/vendor/symfony/service-contracts/Attribute/Required.php
new file mode 100644
index 00000000..bb79ffc0
--- /dev/null
+++ b/vendor/symfony/service-contracts/Attribute/Required.php
@@ -0,0 +1,24 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Contracts\Service\Attribute;
+
+/**
+ * A required dependency.
+ *
+ * This attribute indicates that a property holds a required dependency. The annotated property or method should be
+ * considered during the instantiation process of the containing class.
+ *
+ * @author Alexander M. Turek
+ */
+#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)]
+final class Required
+{
+}
diff --git a/vendor/symfony/service-contracts/Attribute/SubscribedService.php b/vendor/symfony/service-contracts/Attribute/SubscribedService.php
new file mode 100644
index 00000000..1837be6e
--- /dev/null
+++ b/vendor/symfony/service-contracts/Attribute/SubscribedService.php
@@ -0,0 +1,55 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Contracts\Service\Attribute;
+
+use ClassLeak202307\Symfony\Contracts\Service\ServiceSubscriberInterface;
+use ClassLeak202307\Symfony\Contracts\Service\ServiceSubscriberTrait;
+/**
+ * For use as the return value for {@see ServiceSubscriberInterface}.
+ *
+ * @example new SubscribedService('http_client', HttpClientInterface::class, false, new Target('githubApi'))
+ *
+ * Use with {@see ServiceSubscriberTrait} to mark a method's return type
+ * as a subscribed service.
+ *
+ * @author Kevin Bond
+ */
+#[\Attribute(\Attribute::TARGET_METHOD)]
+final class SubscribedService
+{
+ /**
+ * @var string|null
+ */
+ public $key;
+ /**
+ * @var class-string|null
+ */
+ public $type;
+ /**
+ * @var bool
+ */
+ public $nullable = \false;
+ /** @var object[] */
+ public $attributes;
+ /**
+ * @param string|null $key The key to use for the service
+ * @param class-string|null $type The service class
+ * @param bool $nullable Whether the service is optional
+ * @param object|object[] $attributes One or more dependency injection attributes to use
+ */
+ public function __construct(?string $key = null, ?string $type = null, bool $nullable = \false, $attributes = [])
+ {
+ $this->key = $key;
+ $this->type = $type;
+ $this->nullable = $nullable;
+ $this->attributes = \is_array($attributes) ? $attributes : [$attributes];
+ }
+}
diff --git a/vendor/symfony/service-contracts/CHANGELOG.md b/vendor/symfony/service-contracts/CHANGELOG.md
new file mode 100644
index 00000000..7932e261
--- /dev/null
+++ b/vendor/symfony/service-contracts/CHANGELOG.md
@@ -0,0 +1,5 @@
+CHANGELOG
+=========
+
+The changelog is maintained for all Symfony contracts at the following URL:
+https://github.com/symfony/contracts/blob/main/CHANGELOG.md
diff --git a/vendor/symfony/service-contracts/LICENSE b/vendor/symfony/service-contracts/LICENSE
new file mode 100644
index 00000000..7536caea
--- /dev/null
+++ b/vendor/symfony/service-contracts/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2018-present 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
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/symfony/service-contracts/README.md b/vendor/symfony/service-contracts/README.md
new file mode 100644
index 00000000..42841a57
--- /dev/null
+++ b/vendor/symfony/service-contracts/README.md
@@ -0,0 +1,9 @@
+Symfony Service Contracts
+=========================
+
+A set of abstractions extracted out of the Symfony components.
+
+Can be used to build on semantics that the Symfony components proved useful and
+that already have battle tested implementations.
+
+See https://github.com/symfony/contracts/blob/main/README.md for more information.
diff --git a/vendor/symfony/service-contracts/ResetInterface.php b/vendor/symfony/service-contracts/ResetInterface.php
new file mode 100644
index 00000000..8e4698a1
--- /dev/null
+++ b/vendor/symfony/service-contracts/ResetInterface.php
@@ -0,0 +1,32 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Contracts\Service;
+
+/**
+ * Provides a way to reset an object to its initial state.
+ *
+ * When calling the "reset()" method on an object, it should be put back to its
+ * initial state. This usually means clearing any internal buffers and forwarding
+ * the call to internal dependencies. All properties of the object should be put
+ * back to the same state it had when it was first ready to use.
+ *
+ * This method could be called, for example, to recycle objects that are used as
+ * services, so that they can be used to handle several requests in the same
+ * process loop (note that we advise making your services stateless instead of
+ * implementing this interface when possible.)
+ */
+interface ResetInterface
+{
+ /**
+ * @return void
+ */
+ public function reset();
+}
diff --git a/vendor/symfony/service-contracts/ServiceLocatorTrait.php b/vendor/symfony/service-contracts/ServiceLocatorTrait.php
new file mode 100644
index 00000000..0c549474
--- /dev/null
+++ b/vendor/symfony/service-contracts/ServiceLocatorTrait.php
@@ -0,0 +1,112 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Contracts\Service;
+
+use ClassLeak202307\Psr\Container\ContainerExceptionInterface;
+use ClassLeak202307\Psr\Container\NotFoundExceptionInterface;
+// Help opcache.preload discover always-needed symbols
+\class_exists(ContainerExceptionInterface::class);
+\class_exists(NotFoundExceptionInterface::class);
+/**
+ * A trait to help implement ServiceProviderInterface.
+ *
+ * @author Robin Chalas
+ * @author Nicolas Grekas
+ */
+trait ServiceLocatorTrait
+{
+ /**
+ * @var mixed[]
+ */
+ private $factories;
+ /**
+ * @var mixed[]
+ */
+ private $loading = [];
+ /**
+ * @var mixed[]
+ */
+ private $providedTypes;
+ /**
+ * @param callable[] $factories
+ */
+ public function __construct(array $factories)
+ {
+ $this->factories = $factories;
+ }
+ public function has(string $id) : bool
+ {
+ return isset($this->factories[$id]);
+ }
+ /**
+ * @return mixed
+ */
+ public function get(string $id)
+ {
+ if (!isset($this->factories[$id])) {
+ throw $this->createNotFoundException($id);
+ }
+ if (isset($this->loading[$id])) {
+ $ids = \array_values($this->loading);
+ $ids = \array_slice($this->loading, \array_search($id, $ids));
+ $ids[] = $id;
+ throw $this->createCircularReferenceException($id, $ids);
+ }
+ $this->loading[$id] = $id;
+ try {
+ return $this->factories[$id]($this);
+ } finally {
+ unset($this->loading[$id]);
+ }
+ }
+ public function getProvidedServices() : array
+ {
+ if (!isset($this->providedTypes)) {
+ $this->providedTypes = [];
+ foreach ($this->factories as $name => $factory) {
+ if (!\is_callable($factory)) {
+ $this->providedTypes[$name] = '?';
+ } else {
+ $type = (new \ReflectionFunction($factory))->getReturnType();
+ $this->providedTypes[$name] = $type ? ($type->allowsNull() ? '?' : '') . ($type instanceof \ReflectionNamedType ? $type->getName() : $type) : '?';
+ }
+ }
+ }
+ return $this->providedTypes;
+ }
+ private function createNotFoundException(string $id) : NotFoundExceptionInterface
+ {
+ if (!($alternatives = \array_keys($this->factories))) {
+ $message = 'is empty...';
+ } else {
+ $last = \array_pop($alternatives);
+ if ($alternatives) {
+ $message = \sprintf('only knows about the "%s" and "%s" services.', \implode('", "', $alternatives), $last);
+ } else {
+ $message = \sprintf('only knows about the "%s" service.', $last);
+ }
+ }
+ if ($this->loading) {
+ $message = \sprintf('The service "%s" has a dependency on a non-existent service "%s". This locator %s', \end($this->loading), $id, $message);
+ } else {
+ $message = \sprintf('Service "%s" not found: the current service locator %s', $id, $message);
+ }
+ return new class($message) extends \InvalidArgumentException implements NotFoundExceptionInterface
+ {
+ };
+ }
+ private function createCircularReferenceException(string $id, array $path) : ContainerExceptionInterface
+ {
+ return new class(\sprintf('Circular reference detected for service "%s", path: "%s".', $id, \implode(' -> ', $path))) extends \RuntimeException implements ContainerExceptionInterface
+ {
+ };
+ }
+}
diff --git a/vendor/symfony/service-contracts/ServiceProviderInterface.php b/vendor/symfony/service-contracts/ServiceProviderInterface.php
new file mode 100644
index 00000000..f37a6e09
--- /dev/null
+++ b/vendor/symfony/service-contracts/ServiceProviderInterface.php
@@ -0,0 +1,41 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Contracts\Service;
+
+use ClassLeak202307\Psr\Container\ContainerInterface;
+/**
+ * A ServiceProviderInterface exposes the identifiers and the types of services provided by a container.
+ *
+ * @author Nicolas Grekas
+ * @author Mateusz Sip
+ *
+ * @template-covariant T of mixed
+ */
+interface ServiceProviderInterface extends ContainerInterface
+{
+ /**
+ * @return T
+ */
+ public function get(string $id);
+ public function has(string $id) : bool;
+ /**
+ * Returns an associative array of service types keyed by the identifiers provided by the current container.
+ *
+ * Examples:
+ *
+ * * ['logger' => 'Psr\Log\LoggerInterface'] means the object provides a service named "logger" that implements Psr\Log\LoggerInterface
+ * * ['foo' => '?'] means the container provides service name "foo" of unspecified type
+ * * ['bar' => '?Bar\Baz'] means the container provides a service "bar" of type Bar\Baz|null
+ *
+ * @return string[] The provided service types, keyed by service names
+ */
+ public function getProvidedServices() : array;
+}
diff --git a/vendor/symfony/service-contracts/ServiceSubscriberInterface.php b/vendor/symfony/service-contracts/ServiceSubscriberInterface.php
new file mode 100644
index 00000000..e83c45da
--- /dev/null
+++ b/vendor/symfony/service-contracts/ServiceSubscriberInterface.php
@@ -0,0 +1,60 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Contracts\Service;
+
+use ClassLeak202307\Symfony\Contracts\Service\Attribute\SubscribedService;
+/**
+ * A ServiceSubscriber exposes its dependencies via the static {@link getSubscribedServices} method.
+ *
+ * The getSubscribedServices method returns an array of service types required by such instances,
+ * optionally keyed by the service names used internally. Service types that start with an interrogation
+ * mark "?" are optional, while the other ones are mandatory service dependencies.
+ *
+ * The injected service locators SHOULD NOT allow access to any other services not specified by the method.
+ *
+ * It is expected that ServiceSubscriber instances consume PSR-11-based service locators internally.
+ * This interface does not dictate any injection method for these service locators, although constructor
+ * injection is recommended.
+ *
+ * @author Nicolas Grekas
+ */
+interface ServiceSubscriberInterface
+{
+ /**
+ * Returns an array of service types (or {@see SubscribedService} objects) required
+ * by such instances, optionally keyed by the service names used internally.
+ *
+ * For mandatory dependencies:
+ *
+ * * ['logger' => 'Psr\Log\LoggerInterface'] means the objects use the "logger" name
+ * internally to fetch a service which must implement Psr\Log\LoggerInterface.
+ * * ['loggers' => 'Psr\Log\LoggerInterface[]'] means the objects use the "loggers" name
+ * internally to fetch an iterable of Psr\Log\LoggerInterface instances.
+ * * ['Psr\Log\LoggerInterface'] is a shortcut for
+ * * ['Psr\Log\LoggerInterface' => 'Psr\Log\LoggerInterface']
+ *
+ * otherwise:
+ *
+ * * ['logger' => '?Psr\Log\LoggerInterface'] denotes an optional dependency
+ * * ['loggers' => '?Psr\Log\LoggerInterface[]'] denotes an optional iterable dependency
+ * * ['?Psr\Log\LoggerInterface'] is a shortcut for
+ * * ['Psr\Log\LoggerInterface' => '?Psr\Log\LoggerInterface']
+ *
+ * additionally, an array of {@see SubscribedService}'s can be returned:
+ *
+ * * [new SubscribedService('logger', Psr\Log\LoggerInterface::class)]
+ * * [new SubscribedService(type: Psr\Log\LoggerInterface::class, nullable: true)]
+ * * [new SubscribedService('http_client', HttpClientInterface::class, attributes: new Target('githubApi'))]
+ *
+ * @return string[]|SubscribedService[] The required service types, optionally keyed by service names
+ */
+ public static function getSubscribedServices() : array;
+}
diff --git a/vendor/symfony/service-contracts/ServiceSubscriberTrait.php b/vendor/symfony/service-contracts/ServiceSubscriberTrait.php
new file mode 100644
index 00000000..c00e9d7b
--- /dev/null
+++ b/vendor/symfony/service-contracts/ServiceSubscriberTrait.php
@@ -0,0 +1,67 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Contracts\Service;
+
+use ClassLeak202307\Psr\Container\ContainerInterface;
+use ClassLeak202307\Symfony\Contracts\Service\Attribute\Required;
+use ClassLeak202307\Symfony\Contracts\Service\Attribute\SubscribedService;
+/**
+ * Implementation of ServiceSubscriberInterface that determines subscribed services from
+ * method return types. Service ids are available as "ClassName::methodName".
+ *
+ * @author Kevin Bond
+ */
+trait ServiceSubscriberTrait
+{
+ /** @var ContainerInterface */
+ protected $container;
+ public static function getSubscribedServices() : array
+ {
+ $services = \method_exists(\get_parent_class(self::class) ?: '', __FUNCTION__) ? parent::getSubscribedServices() : [];
+ foreach ((new \ReflectionClass(self::class))->getMethods() as $method) {
+ if (self::class !== $method->getDeclaringClass()->name) {
+ continue;
+ }
+ if (!($attribute = (\method_exists($method, 'getAttributes') ? $method->getAttributes(SubscribedService::class) : [])[0] ?? null)) {
+ continue;
+ }
+ if ($method->isStatic() || $method->isAbstract() || $method->isGenerator() || $method->isInternal() || $method->getNumberOfRequiredParameters()) {
+ throw new \LogicException(\sprintf('Cannot use "%s" on method "%s::%s()" (can only be used on non-static, non-abstract methods with no parameters).', SubscribedService::class, self::class, $method->name));
+ }
+ if (!($returnType = $method->getReturnType())) {
+ throw new \LogicException(\sprintf('Cannot use "%s" on methods without a return type in "%s::%s()".', SubscribedService::class, $method->name, self::class));
+ }
+ /* @var SubscribedService $attribute */
+ $attribute = $attribute->newInstance();
+ $attribute->key = $attribute->key ?? self::class . '::' . $method->name;
+ $attribute->type = $attribute->type ?? ($returnType instanceof \ReflectionNamedType ? $returnType->getName() : (string) $returnType);
+ $attribute->nullable = $returnType->allowsNull();
+ if ($attribute->attributes) {
+ $services[] = $attribute;
+ } else {
+ $services[$attribute->key] = ($attribute->nullable ? '?' : '') . $attribute->type;
+ }
+ }
+ return $services;
+ }
+ /**
+ * @required
+ */
+ public function setContainer(ContainerInterface $container) : ?ContainerInterface
+ {
+ $ret = null;
+ if (\method_exists(\get_parent_class(self::class) ?: '', __FUNCTION__)) {
+ $ret = parent::setContainer($container);
+ }
+ $this->container = $container;
+ return $ret;
+ }
+}
diff --git a/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php b/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php
new file mode 100644
index 00000000..487418d4
--- /dev/null
+++ b/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php
@@ -0,0 +1,21 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Contracts\Service\Test;
+
+\class_alias(ServiceLocatorTestCase::class, ServiceLocatorTest::class);
+if (\false) {
+ /**
+ * @deprecated since PHPUnit 9.6
+ */
+ class ServiceLocatorTest
+ {
+ }
+}
diff --git a/vendor/symfony/service-contracts/Test/ServiceLocatorTestCase.php b/vendor/symfony/service-contracts/Test/ServiceLocatorTestCase.php
new file mode 100644
index 00000000..0d2b91de
--- /dev/null
+++ b/vendor/symfony/service-contracts/Test/ServiceLocatorTestCase.php
@@ -0,0 +1,83 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Contracts\Service\Test;
+
+use ClassLeak202307\PHPUnit\Framework\TestCase;
+use ClassLeak202307\Psr\Container\ContainerInterface;
+use ClassLeak202307\Symfony\Contracts\Service\ServiceLocatorTrait;
+abstract class ServiceLocatorTestCase extends TestCase
+{
+ protected function getServiceLocator(array $factories) : ContainerInterface
+ {
+ return new class($factories) implements ContainerInterface
+ {
+ use ServiceLocatorTrait;
+ };
+ }
+ public function testHas()
+ {
+ $locator = $this->getServiceLocator(['foo' => function () {
+ return 'bar';
+ }, 'bar' => function () {
+ return 'baz';
+ }, function () {
+ return 'dummy';
+ }]);
+ $this->assertTrue($locator->has('foo'));
+ $this->assertTrue($locator->has('bar'));
+ $this->assertFalse($locator->has('dummy'));
+ }
+ public function testGet()
+ {
+ $locator = $this->getServiceLocator(['foo' => function () {
+ return 'bar';
+ }, 'bar' => function () {
+ return 'baz';
+ }]);
+ $this->assertSame('bar', $locator->get('foo'));
+ $this->assertSame('baz', $locator->get('bar'));
+ }
+ public function testGetDoesNotMemoize()
+ {
+ $i = 0;
+ $locator = $this->getServiceLocator(['foo' => function () use(&$i) {
+ ++$i;
+ return 'bar';
+ }]);
+ $this->assertSame('bar', $locator->get('foo'));
+ $this->assertSame('bar', $locator->get('foo'));
+ $this->assertSame(2, $i);
+ }
+ public function testThrowsOnUndefinedInternalService()
+ {
+ if (!$this->getExpectedException()) {
+ $this->expectException(\ClassLeak202307\Psr\Container\NotFoundExceptionInterface::class);
+ $this->expectExceptionMessage('The service "foo" has a dependency on a non-existent service "bar". This locator only knows about the "foo" service.');
+ }
+ $locator = $this->getServiceLocator(['foo' => function () use(&$locator) {
+ return $locator->get('bar');
+ }]);
+ $locator->get('foo');
+ }
+ public function testThrowsOnCircularReference()
+ {
+ $this->expectException(\ClassLeak202307\Psr\Container\ContainerExceptionInterface::class);
+ $this->expectExceptionMessage('Circular reference detected for service "bar", path: "bar -> baz -> bar".');
+ $locator = $this->getServiceLocator(['foo' => function () use(&$locator) {
+ return $locator->get('bar');
+ }, 'bar' => function () use(&$locator) {
+ return $locator->get('baz');
+ }, 'baz' => function () use(&$locator) {
+ return $locator->get('bar');
+ }]);
+ $locator->get('foo');
+ }
+}
diff --git a/vendor/symfony/service-contracts/composer.json b/vendor/symfony/service-contracts/composer.json
new file mode 100644
index 00000000..813b1c80
--- /dev/null
+++ b/vendor/symfony/service-contracts/composer.json
@@ -0,0 +1,50 @@
+{
+ "name": "symfony\/service-contracts",
+ "type": "library",
+ "description": "Generic abstractions related to writing services",
+ "keywords": [
+ "abstractions",
+ "contracts",
+ "decoupling",
+ "interfaces",
+ "interoperability",
+ "standards"
+ ],
+ "homepage": "https:\/\/symfony.com",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https:\/\/symfony.com\/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=8.1",
+ "psr\/container": "^2.0"
+ },
+ "conflict": {
+ "ext-psr": "<1.1|>=2"
+ },
+ "autoload": {
+ "psr-4": {
+ "ClassLeak202307\\Symfony\\Contracts\\Service\\": ""
+ },
+ "exclude-from-classmap": [
+ "\/Test\/"
+ ]
+ },
+ "minimum-stability": "dev",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.4-dev"
+ },
+ "thanks": {
+ "name": "symfony\/contracts",
+ "url": "https:\/\/github.com\/symfony\/contracts"
+ }
+ }
+}
\ No newline at end of file
diff --git a/vendor/symfony/string/AbstractString.php b/vendor/symfony/string/AbstractString.php
new file mode 100644
index 00000000..8f556db8
--- /dev/null
+++ b/vendor/symfony/string/AbstractString.php
@@ -0,0 +1,646 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\String;
+
+use ClassLeak202307\Symfony\Component\String\Exception\ExceptionInterface;
+use ClassLeak202307\Symfony\Component\String\Exception\InvalidArgumentException;
+use ClassLeak202307\Symfony\Component\String\Exception\RuntimeException;
+/**
+ * Represents a string of abstract characters.
+ *
+ * Unicode defines 3 types of "characters" (bytes, code points and grapheme clusters).
+ * This class is the abstract type to use as a type-hint when the logic you want to
+ * implement doesn't care about the exact variant it deals with.
+ *
+ * @author Nicolas Grekas
+ * @author Hugo Hamon
+ *
+ * @throws ExceptionInterface
+ */
+abstract class AbstractString implements \JsonSerializable
+{
+ public const PREG_PATTERN_ORDER = \PREG_PATTERN_ORDER;
+ public const PREG_SET_ORDER = \PREG_SET_ORDER;
+ public const PREG_OFFSET_CAPTURE = \PREG_OFFSET_CAPTURE;
+ public const PREG_UNMATCHED_AS_NULL = \PREG_UNMATCHED_AS_NULL;
+ public const PREG_SPLIT = 0;
+ public const PREG_SPLIT_NO_EMPTY = \PREG_SPLIT_NO_EMPTY;
+ public const PREG_SPLIT_DELIM_CAPTURE = \PREG_SPLIT_DELIM_CAPTURE;
+ public const PREG_SPLIT_OFFSET_CAPTURE = \PREG_SPLIT_OFFSET_CAPTURE;
+ protected $string = '';
+ protected $ignoreCase = \false;
+ public abstract function __construct(string $string = '');
+ /**
+ * Unwraps instances of AbstractString back to strings.
+ *
+ * @return string[]|array
+ */
+ public static function unwrap(array $values) : array
+ {
+ foreach ($values as $k => $v) {
+ if ($v instanceof self) {
+ $values[$k] = $v->__toString();
+ } elseif (\is_array($v) && $values[$k] !== ($v = static::unwrap($v))) {
+ $values[$k] = $v;
+ }
+ }
+ return $values;
+ }
+ /**
+ * Wraps (and normalizes) strings in instances of AbstractString.
+ *
+ * @return static[]|array
+ */
+ public static function wrap(array $values) : array
+ {
+ $i = 0;
+ $keys = null;
+ foreach ($values as $k => $v) {
+ if (\is_string($k) && '' !== $k && $k !== ($j = (string) new static($k))) {
+ $keys = $keys ?? \array_keys($values);
+ $keys[$i] = $j;
+ }
+ if (\is_string($v)) {
+ $values[$k] = new static($v);
+ } elseif (\is_array($v) && $values[$k] !== ($v = static::wrap($v))) {
+ $values[$k] = $v;
+ }
+ ++$i;
+ }
+ return null !== $keys ? \array_combine($keys, $values) : $values;
+ }
+ /**
+ * @param string|string[] $needle
+ * @return $this
+ */
+ public function after($needle, bool $includeNeedle = \false, int $offset = 0)
+ {
+ $str = clone $this;
+ $i = \PHP_INT_MAX;
+ if (\is_string($needle)) {
+ $needle = [$needle];
+ }
+ foreach ($needle as $n) {
+ $n = (string) $n;
+ $j = $this->indexOf($n, $offset);
+ if (null !== $j && $j < $i) {
+ $i = $j;
+ $str->string = $n;
+ }
+ }
+ if (\PHP_INT_MAX === $i) {
+ return $str;
+ }
+ if (!$includeNeedle) {
+ $i += $str->length();
+ }
+ return $this->slice($i);
+ }
+ /**
+ * @param string|string[] $needle
+ * @return $this
+ */
+ public function afterLast($needle, bool $includeNeedle = \false, int $offset = 0)
+ {
+ $str = clone $this;
+ $i = null;
+ if (\is_string($needle)) {
+ $needle = [$needle];
+ }
+ foreach ($needle as $n) {
+ $n = (string) $n;
+ $j = $this->indexOfLast($n, $offset);
+ if (null !== $j && $j >= $i) {
+ $i = $offset = $j;
+ $str->string = $n;
+ }
+ }
+ if (null === $i) {
+ return $str;
+ }
+ if (!$includeNeedle) {
+ $i += $str->length();
+ }
+ return $this->slice($i);
+ }
+ /**
+ * @return $this
+ */
+ public abstract function append(string ...$suffix);
+ /**
+ * @param string|string[] $needle
+ * @return $this
+ */
+ public function before($needle, bool $includeNeedle = \false, int $offset = 0)
+ {
+ $str = clone $this;
+ $i = \PHP_INT_MAX;
+ if (\is_string($needle)) {
+ $needle = [$needle];
+ }
+ foreach ($needle as $n) {
+ $n = (string) $n;
+ $j = $this->indexOf($n, $offset);
+ if (null !== $j && $j < $i) {
+ $i = $j;
+ $str->string = $n;
+ }
+ }
+ if (\PHP_INT_MAX === $i) {
+ return $str;
+ }
+ if ($includeNeedle) {
+ $i += $str->length();
+ }
+ return $this->slice(0, $i);
+ }
+ /**
+ * @param string|string[] $needle
+ * @return $this
+ */
+ public function beforeLast($needle, bool $includeNeedle = \false, int $offset = 0)
+ {
+ $str = clone $this;
+ $i = null;
+ if (\is_string($needle)) {
+ $needle = [$needle];
+ }
+ foreach ($needle as $n) {
+ $n = (string) $n;
+ $j = $this->indexOfLast($n, $offset);
+ if (null !== $j && $j >= $i) {
+ $i = $offset = $j;
+ $str->string = $n;
+ }
+ }
+ if (null === $i) {
+ return $str;
+ }
+ if ($includeNeedle) {
+ $i += $str->length();
+ }
+ return $this->slice(0, $i);
+ }
+ /**
+ * @return int[]
+ */
+ public function bytesAt(int $offset) : array
+ {
+ $str = $this->slice($offset, 1);
+ return '' === $str->string ? [] : \array_values(\unpack('C*', $str->string));
+ }
+ /**
+ * @return $this
+ */
+ public abstract function camel();
+ /**
+ * @return static[]
+ */
+ public abstract function chunk(int $length = 1) : array;
+ /**
+ * @return $this
+ */
+ public function collapseWhitespace()
+ {
+ $str = clone $this;
+ $str->string = \trim(\preg_replace("/(?:[ \n\r\t\f]{2,}+|[\n\r\t\f])/", ' ', $str->string), " \n\r\t\f");
+ return $str;
+ }
+ /**
+ * @param string|string[] $needle
+ */
+ public function containsAny($needle) : bool
+ {
+ return null !== $this->indexOf($needle);
+ }
+ /**
+ * @param string|string[] $suffix
+ */
+ public function endsWith($suffix) : bool
+ {
+ if (\is_string($suffix)) {
+ throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
+ }
+ foreach ($suffix as $s) {
+ if ($this->endsWith((string) $s)) {
+ return \true;
+ }
+ }
+ return \false;
+ }
+ /**
+ * @return $this
+ */
+ public function ensureEnd(string $suffix)
+ {
+ if (!$this->endsWith($suffix)) {
+ return $this->append($suffix);
+ }
+ $suffix = \preg_quote($suffix);
+ $regex = '{(' . $suffix . ')(?:' . $suffix . ')++$}D';
+ return $this->replaceMatches($regex . ($this->ignoreCase ? 'i' : ''), '$1');
+ }
+ /**
+ * @return $this
+ */
+ public function ensureStart(string $prefix)
+ {
+ $prefix = new static($prefix);
+ if (!$this->startsWith($prefix)) {
+ return $this->prepend($prefix);
+ }
+ $str = clone $this;
+ $i = $prefixLen = $prefix->length();
+ while ($this->indexOf($prefix, $i) === $i) {
+ $str = $str->slice($prefixLen);
+ $i += $prefixLen;
+ }
+ return $str;
+ }
+ /**
+ * @param string|string[] $string
+ */
+ public function equalsTo($string) : bool
+ {
+ if (\is_string($string)) {
+ throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
+ }
+ foreach ($string as $s) {
+ if ($this->equalsTo((string) $s)) {
+ return \true;
+ }
+ }
+ return \false;
+ }
+ /**
+ * @return $this
+ */
+ public abstract function folded();
+ /**
+ * @return $this
+ */
+ public function ignoreCase()
+ {
+ $str = clone $this;
+ $str->ignoreCase = \true;
+ return $str;
+ }
+ /**
+ * @param string|string[] $needle
+ */
+ public function indexOf($needle, int $offset = 0) : ?int
+ {
+ if (\is_string($needle)) {
+ throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
+ }
+ $i = \PHP_INT_MAX;
+ foreach ($needle as $n) {
+ $j = $this->indexOf((string) $n, $offset);
+ if (null !== $j && $j < $i) {
+ $i = $j;
+ }
+ }
+ return \PHP_INT_MAX === $i ? null : $i;
+ }
+ /**
+ * @param string|string[] $needle
+ */
+ public function indexOfLast($needle, int $offset = 0) : ?int
+ {
+ if (\is_string($needle)) {
+ throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
+ }
+ $i = null;
+ foreach ($needle as $n) {
+ $j = $this->indexOfLast((string) $n, $offset);
+ if (null !== $j && $j >= $i) {
+ $i = $offset = $j;
+ }
+ }
+ return $i;
+ }
+ public function isEmpty() : bool
+ {
+ return '' === $this->string;
+ }
+ /**
+ * @return $this
+ */
+ public abstract function join(array $strings, string $lastGlue = null);
+ public function jsonSerialize() : string
+ {
+ return $this->string;
+ }
+ public abstract function length() : int;
+ /**
+ * @return $this
+ */
+ public abstract function lower();
+ /**
+ * Matches the string using a regular expression.
+ *
+ * Pass PREG_PATTERN_ORDER or PREG_SET_ORDER as $flags to get all occurrences matching the regular expression.
+ *
+ * @return array All matches in a multi-dimensional array ordered according to flags
+ */
+ public abstract function match(string $regexp, int $flags = 0, int $offset = 0) : array;
+ /**
+ * @return $this
+ */
+ public abstract function padBoth(int $length, string $padStr = ' ');
+ /**
+ * @return $this
+ */
+ public abstract function padEnd(int $length, string $padStr = ' ');
+ /**
+ * @return $this
+ */
+ public abstract function padStart(int $length, string $padStr = ' ');
+ /**
+ * @return $this
+ */
+ public abstract function prepend(string ...$prefix);
+ /**
+ * @return $this
+ */
+ public function repeat(int $multiplier)
+ {
+ if (0 > $multiplier) {
+ throw new InvalidArgumentException(\sprintf('Multiplier must be positive, %d given.', $multiplier));
+ }
+ $str = clone $this;
+ $str->string = \str_repeat($str->string, $multiplier);
+ return $str;
+ }
+ /**
+ * @return $this
+ */
+ public abstract function replace(string $from, string $to);
+ /**
+ * @param string|callable $to
+ * @return $this
+ */
+ public abstract function replaceMatches(string $fromRegexp, $to);
+ /**
+ * @return $this
+ */
+ public abstract function reverse();
+ /**
+ * @return $this
+ */
+ public abstract function slice(int $start = 0, int $length = null);
+ /**
+ * @return $this
+ */
+ public abstract function snake();
+ /**
+ * @return $this
+ */
+ public abstract function splice(string $replacement, int $start = 0, int $length = null);
+ /**
+ * @return static[]
+ */
+ public function split(string $delimiter, int $limit = null, int $flags = null) : array
+ {
+ if (null === $flags) {
+ throw new \TypeError('Split behavior when $flags is null must be implemented by child classes.');
+ }
+ if ($this->ignoreCase) {
+ $delimiter .= 'i';
+ }
+ \set_error_handler(static function ($t, $m) {
+ throw new InvalidArgumentException($m);
+ });
+ try {
+ if (\false === ($chunks = \preg_split($delimiter, $this->string, $limit, $flags))) {
+ throw new RuntimeException('Splitting failed with error: ' . \preg_last_error_msg());
+ }
+ } finally {
+ \restore_error_handler();
+ }
+ $str = clone $this;
+ if (self::PREG_SPLIT_OFFSET_CAPTURE & $flags) {
+ foreach ($chunks as &$chunk) {
+ $str->string = $chunk[0];
+ $chunk[0] = clone $str;
+ }
+ } else {
+ foreach ($chunks as &$chunk) {
+ $str->string = $chunk;
+ $chunk = clone $str;
+ }
+ }
+ return $chunks;
+ }
+ /**
+ * @param string|string[] $prefix
+ */
+ public function startsWith($prefix) : bool
+ {
+ if (\is_string($prefix)) {
+ throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
+ }
+ foreach ($prefix as $prefix) {
+ if ($this->startsWith((string) $prefix)) {
+ return \true;
+ }
+ }
+ return \false;
+ }
+ /**
+ * @return $this
+ */
+ public abstract function title(bool $allWords = \false);
+ public function toByteString(string $toEncoding = null) : ByteString
+ {
+ $b = new ByteString();
+ $toEncoding = \in_array($toEncoding, ['utf8', 'utf-8', 'UTF8'], \true) ? 'UTF-8' : $toEncoding;
+ if (null === $toEncoding || $toEncoding === ($fromEncoding = $this instanceof AbstractUnicodeString || \preg_match('//u', $b->string) ? 'UTF-8' : 'Windows-1252')) {
+ $b->string = $this->string;
+ return $b;
+ }
+ \set_error_handler(static function ($t, $m) {
+ throw new InvalidArgumentException($m);
+ });
+ try {
+ try {
+ $b->string = \mb_convert_encoding($this->string, $toEncoding, 'UTF-8');
+ } catch (InvalidArgumentException $e) {
+ if (!\function_exists('iconv')) {
+ throw $e;
+ }
+ $b->string = \iconv('UTF-8', $toEncoding, $this->string);
+ }
+ } finally {
+ \restore_error_handler();
+ }
+ return $b;
+ }
+ public function toCodePointString() : CodePointString
+ {
+ return new CodePointString($this->string);
+ }
+ public function toString() : string
+ {
+ return $this->string;
+ }
+ public function toUnicodeString() : UnicodeString
+ {
+ return new UnicodeString($this->string);
+ }
+ /**
+ * @return $this
+ */
+ public abstract function trim(string $chars = " \t\n\r\x00\v\f ");
+ /**
+ * @return $this
+ */
+ public abstract function trimEnd(string $chars = " \t\n\r\x00\v\f ");
+ /**
+ * @param string|string[] $prefix
+ * @return $this
+ */
+ public function trimPrefix($prefix)
+ {
+ if (\is_array($prefix) || $prefix instanceof \Traversable) {
+ // don't use is_iterable(), it's slow
+ foreach ($prefix as $s) {
+ $t = $this->trimPrefix($s);
+ if ($t->string !== $this->string) {
+ return $t;
+ }
+ }
+ return clone $this;
+ }
+ $str = clone $this;
+ if ($prefix instanceof self) {
+ $prefix = $prefix->string;
+ } else {
+ $prefix = (string) $prefix;
+ }
+ if ('' !== $prefix && \strlen($this->string) >= \strlen($prefix) && 0 === \substr_compare($this->string, $prefix, 0, \strlen($prefix), $this->ignoreCase)) {
+ $str->string = \substr($this->string, \strlen($prefix));
+ }
+ return $str;
+ }
+ /**
+ * @return $this
+ */
+ public abstract function trimStart(string $chars = " \t\n\r\x00\v\f ");
+ /**
+ * @param string|string[] $suffix
+ * @return $this
+ */
+ public function trimSuffix($suffix)
+ {
+ if (\is_array($suffix) || $suffix instanceof \Traversable) {
+ // don't use is_iterable(), it's slow
+ foreach ($suffix as $s) {
+ $t = $this->trimSuffix($s);
+ if ($t->string !== $this->string) {
+ return $t;
+ }
+ }
+ return clone $this;
+ }
+ $str = clone $this;
+ if ($suffix instanceof self) {
+ $suffix = $suffix->string;
+ } else {
+ $suffix = (string) $suffix;
+ }
+ if ('' !== $suffix && \strlen($this->string) >= \strlen($suffix) && 0 === \substr_compare($this->string, $suffix, -\strlen($suffix), null, $this->ignoreCase)) {
+ $str->string = \substr($this->string, 0, -\strlen($suffix));
+ }
+ return $str;
+ }
+ /**
+ * @return $this
+ */
+ public function truncate(int $length, string $ellipsis = '', bool $cut = \true)
+ {
+ $stringLength = $this->length();
+ if ($stringLength <= $length) {
+ return clone $this;
+ }
+ $ellipsisLength = '' !== $ellipsis ? (new static($ellipsis))->length() : 0;
+ if ($length < $ellipsisLength) {
+ $ellipsisLength = 0;
+ }
+ if (!$cut) {
+ if (null === ($length = $this->indexOf([' ', "\r", "\n", "\t"], ($length ?: 1) - 1))) {
+ return clone $this;
+ }
+ $length += $ellipsisLength;
+ }
+ $str = $this->slice(0, $length - $ellipsisLength);
+ return $ellipsisLength ? $str->trimEnd()->append($ellipsis) : $str;
+ }
+ /**
+ * @return $this
+ */
+ public abstract function upper();
+ /**
+ * Returns the printable length on a terminal.
+ */
+ public abstract function width(bool $ignoreAnsiDecoration = \true) : int;
+ /**
+ * @return $this
+ */
+ public function wordwrap(int $width = 75, string $break = "\n", bool $cut = \false)
+ {
+ $lines = '' !== $break ? $this->split($break) : [clone $this];
+ $chars = [];
+ $mask = '';
+ if (1 === \count($lines) && '' === $lines[0]->string) {
+ return $lines[0];
+ }
+ foreach ($lines as $i => $line) {
+ if ($i) {
+ $chars[] = $break;
+ $mask .= '#';
+ }
+ foreach ($line->chunk() as $char) {
+ $chars[] = $char->string;
+ $mask .= ' ' === $char->string ? ' ' : '?';
+ }
+ }
+ $string = '';
+ $j = 0;
+ $b = $i = -1;
+ $mask = \wordwrap($mask, $width, '#', $cut);
+ while (\false !== ($b = \strpos($mask, '#', $b + 1))) {
+ for (++$i; $i < $b; ++$i) {
+ $string .= $chars[$j];
+ unset($chars[$j++]);
+ }
+ if ($break === $chars[$j] || ' ' === $chars[$j]) {
+ unset($chars[$j++]);
+ }
+ $string .= $break;
+ }
+ $str = clone $this;
+ $str->string = $string . \implode('', $chars);
+ return $str;
+ }
+ public function __sleep() : array
+ {
+ return ['string'];
+ }
+ public function __clone()
+ {
+ $this->ignoreCase = \false;
+ }
+ public function __toString() : string
+ {
+ return $this->string;
+ }
+}
diff --git a/vendor/symfony/string/AbstractUnicodeString.php b/vendor/symfony/string/AbstractUnicodeString.php
new file mode 100644
index 00000000..8e95b60f
--- /dev/null
+++ b/vendor/symfony/string/AbstractUnicodeString.php
@@ -0,0 +1,523 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\String;
+
+use ClassLeak202307\Symfony\Component\String\Exception\ExceptionInterface;
+use ClassLeak202307\Symfony\Component\String\Exception\InvalidArgumentException;
+use ClassLeak202307\Symfony\Component\String\Exception\RuntimeException;
+/**
+ * Represents a string of abstract Unicode characters.
+ *
+ * Unicode defines 3 types of "characters" (bytes, code points and grapheme clusters).
+ * This class is the abstract type to use as a type-hint when the logic you want to
+ * implement is Unicode-aware but doesn't care about code points vs grapheme clusters.
+ *
+ * @author Nicolas Grekas
+ *
+ * @throws ExceptionInterface
+ */
+abstract class AbstractUnicodeString extends AbstractString
+{
+ public const NFC = \Normalizer::NFC;
+ public const NFD = \Normalizer::NFD;
+ public const NFKC = \Normalizer::NFKC;
+ public const NFKD = \Normalizer::NFKD;
+ // all ASCII letters sorted by typical frequency of occurrence
+ private const ASCII = " eiasntrolud][cmp'\ng|hv.fb,:=-q10C2*yx)(L9AS/P\"EjMIk3>5T>', '<', '>', '-', '-', '-', '-', '-', '-', '-', '-', '-', '||', '/', '[', ']', '*', ',', '.', '<', '>', '<<', '>>', '[', ']', '[', ']', '[', ']', ',', '.', '[', ']', '<<', '>>', '<', '>', ',', '[', ']', '((', '))', '.', ',', '*', '/', '-', '/', '\\', '|', '||', '<<', '>>', '((', '))'];
+ private static $transliterators = [];
+ private static $tableZero;
+ private static $tableWide;
+ /**
+ * @return $this
+ */
+ public static function fromCodePoints(int ...$codes)
+ {
+ $string = '';
+ foreach ($codes as $code) {
+ if (0x80 > ($code %= 0x200000)) {
+ $string .= \chr($code);
+ } elseif (0x800 > $code) {
+ $string .= \chr(0xc0 | $code >> 6) . \chr(0x80 | $code & 0x3f);
+ } elseif (0x10000 > $code) {
+ $string .= \chr(0xe0 | $code >> 12) . \chr(0x80 | $code >> 6 & 0x3f) . \chr(0x80 | $code & 0x3f);
+ } else {
+ $string .= \chr(0xf0 | $code >> 18) . \chr(0x80 | $code >> 12 & 0x3f) . \chr(0x80 | $code >> 6 & 0x3f) . \chr(0x80 | $code & 0x3f);
+ }
+ }
+ return new static($string);
+ }
+ /**
+ * Generic UTF-8 to ASCII transliteration.
+ *
+ * Install the intl extension for best results.
+ *
+ * @param string[]|\Transliterator[]|\Closure[] $rules See "*-Latin" rules from Transliterator::listIDs()
+ */
+ public function ascii(array $rules = []) : self
+ {
+ $str = clone $this;
+ $s = $str->string;
+ $str->string = '';
+ \array_unshift($rules, 'nfd');
+ $rules[] = 'latin-ascii';
+ if (\function_exists('transliterator_transliterate')) {
+ $rules[] = 'any-latin/bgn';
+ }
+ $rules[] = 'nfkd';
+ $rules[] = '[:nonspacing mark:] remove';
+ while (\strlen($s) - 1 > ($i = \strspn($s, self::ASCII))) {
+ if (0 < --$i) {
+ $str->string .= \substr($s, 0, $i);
+ $s = \substr($s, $i);
+ }
+ if (!($rule = \array_shift($rules))) {
+ $rules = [];
+ // An empty rule interrupts the next ones
+ }
+ if ($rule instanceof \Transliterator) {
+ $s = $rule->transliterate($s);
+ } elseif ($rule instanceof \Closure) {
+ $s = $rule($s);
+ } elseif ($rule) {
+ if ('nfd' === ($rule = \strtolower($rule))) {
+ \normalizer_is_normalized($s, self::NFD) ?: ($s = \normalizer_normalize($s, self::NFD));
+ } elseif ('nfkd' === $rule) {
+ \normalizer_is_normalized($s, self::NFKD) ?: ($s = \normalizer_normalize($s, self::NFKD));
+ } elseif ('[:nonspacing mark:] remove' === $rule) {
+ $s = \preg_replace('/\\p{Mn}++/u', '', $s);
+ } elseif ('latin-ascii' === $rule) {
+ $s = \str_replace(self::TRANSLIT_FROM, self::TRANSLIT_TO, $s);
+ } elseif ('de-ascii' === $rule) {
+ $s = \preg_replace("/([AUO])̈(?=\\p{Ll})/u", '$1e', $s);
+ $s = \str_replace(["ä", "ö", "ü", "Ä", "Ö", "Ü"], ['ae', 'oe', 'ue', 'AE', 'OE', 'UE'], $s);
+ } elseif (\function_exists('transliterator_transliterate')) {
+ if (null === ($transliterator = self::$transliterators[$rule] = self::$transliterators[$rule] ?? \Transliterator::create($rule))) {
+ if ('any-latin/bgn' === $rule) {
+ $rule = 'any-latin';
+ $transliterator = self::$transliterators[$rule] = self::$transliterators[$rule] ?? \Transliterator::create($rule);
+ }
+ if (null === $transliterator) {
+ throw new InvalidArgumentException(\sprintf('Unknown transliteration rule "%s".', $rule));
+ }
+ self::$transliterators['any-latin/bgn'] = $transliterator;
+ }
+ $s = $transliterator->transliterate($s);
+ }
+ } elseif (!\function_exists('iconv')) {
+ $s = \preg_replace('/[^\\x00-\\x7F]/u', '?', $s);
+ } else {
+ $s = @\preg_replace_callback('/[^\\x00-\\x7F]/u', static function ($c) {
+ $c = (string) \iconv('UTF-8', 'ASCII//TRANSLIT', $c[0]);
+ if ('' === $c && '' === \iconv('UTF-8', 'ASCII//TRANSLIT', '²')) {
+ throw new \LogicException(\sprintf('"%s" requires a translit-able iconv implementation, try installing "gnu-libiconv" if you\'re using Alpine Linux.', static::class));
+ }
+ return 1 < \strlen($c) ? \ltrim($c, '\'`"^~') : ('' !== $c ? $c : '?');
+ }, $s);
+ }
+ }
+ $str->string .= $s;
+ return $str;
+ }
+ /**
+ * @return $this
+ */
+ public function camel()
+ {
+ $str = clone $this;
+ $str->string = \str_replace(' ', '', \preg_replace_callback('/\\b.(?![A-Z]{2,})/u', static function ($m) {
+ static $i = 0;
+ return 1 === ++$i ? 'İ' === $m[0] ? 'i̇' : \mb_strtolower($m[0], 'UTF-8') : \mb_convert_case($m[0], \MB_CASE_TITLE, 'UTF-8');
+ }, \preg_replace('/[^\\pL0-9]++/u', ' ', $this->string)));
+ return $str;
+ }
+ /**
+ * @return int[]
+ */
+ public function codePointsAt(int $offset) : array
+ {
+ $str = $this->slice($offset, 1);
+ if ('' === $str->string) {
+ return [];
+ }
+ $codePoints = [];
+ foreach (\preg_split('//u', $str->string, -1, \PREG_SPLIT_NO_EMPTY) as $c) {
+ $codePoints[] = \mb_ord($c, 'UTF-8');
+ }
+ return $codePoints;
+ }
+ /**
+ * @return $this
+ */
+ public function folded(bool $compat = \true)
+ {
+ $str = clone $this;
+ if (!$compat || !\defined('Normalizer::NFKC_CF')) {
+ $str->string = \normalizer_normalize($str->string, $compat ? \Normalizer::NFKC : \Normalizer::NFC);
+ $str->string = \mb_strtolower(\str_replace(self::FOLD_FROM, self::FOLD_TO, $this->string), 'UTF-8');
+ } else {
+ $str->string = \normalizer_normalize($str->string, \Normalizer::NFKC_CF);
+ }
+ return $str;
+ }
+ /**
+ * @return $this
+ */
+ public function join(array $strings, string $lastGlue = null)
+ {
+ $str = clone $this;
+ $tail = null !== $lastGlue && 1 < \count($strings) ? $lastGlue . \array_pop($strings) : '';
+ $str->string = \implode($this->string, $strings) . $tail;
+ if (!\preg_match('//u', $str->string)) {
+ throw new InvalidArgumentException('Invalid UTF-8 string.');
+ }
+ return $str;
+ }
+ /**
+ * @return $this
+ */
+ public function lower()
+ {
+ $str = clone $this;
+ $str->string = \mb_strtolower(\str_replace('İ', 'i̇', $str->string), 'UTF-8');
+ return $str;
+ }
+ public function match(string $regexp, int $flags = 0, int $offset = 0) : array
+ {
+ $match = (\PREG_PATTERN_ORDER | \PREG_SET_ORDER) & $flags ? 'preg_match_all' : 'preg_match';
+ if ($this->ignoreCase) {
+ $regexp .= 'i';
+ }
+ \set_error_handler(static function ($t, $m) {
+ throw new InvalidArgumentException($m);
+ });
+ try {
+ if (\false === $match($regexp . 'u', $this->string, $matches, $flags | \PREG_UNMATCHED_AS_NULL, $offset)) {
+ throw new RuntimeException('Matching failed with error: ' . \preg_last_error_msg());
+ }
+ } finally {
+ \restore_error_handler();
+ }
+ return $matches;
+ }
+ /**
+ * @return $this
+ */
+ public function normalize(int $form = self::NFC)
+ {
+ if (!\in_array($form, [self::NFC, self::NFD, self::NFKC, self::NFKD])) {
+ throw new InvalidArgumentException('Unsupported normalization form.');
+ }
+ $str = clone $this;
+ \normalizer_is_normalized($str->string, $form) ?: ($str->string = \normalizer_normalize($str->string, $form));
+ return $str;
+ }
+ /**
+ * @return $this
+ */
+ public function padBoth(int $length, string $padStr = ' ')
+ {
+ if ('' === $padStr || !\preg_match('//u', $padStr)) {
+ throw new InvalidArgumentException('Invalid UTF-8 string.');
+ }
+ $pad = clone $this;
+ $pad->string = $padStr;
+ return $this->pad($length, $pad, \STR_PAD_BOTH);
+ }
+ /**
+ * @return $this
+ */
+ public function padEnd(int $length, string $padStr = ' ')
+ {
+ if ('' === $padStr || !\preg_match('//u', $padStr)) {
+ throw new InvalidArgumentException('Invalid UTF-8 string.');
+ }
+ $pad = clone $this;
+ $pad->string = $padStr;
+ return $this->pad($length, $pad, \STR_PAD_RIGHT);
+ }
+ /**
+ * @return $this
+ */
+ public function padStart(int $length, string $padStr = ' ')
+ {
+ if ('' === $padStr || !\preg_match('//u', $padStr)) {
+ throw new InvalidArgumentException('Invalid UTF-8 string.');
+ }
+ $pad = clone $this;
+ $pad->string = $padStr;
+ return $this->pad($length, $pad, \STR_PAD_LEFT);
+ }
+ /**
+ * @param string|callable $to
+ * @return $this
+ */
+ public function replaceMatches(string $fromRegexp, $to)
+ {
+ if ($this->ignoreCase) {
+ $fromRegexp .= 'i';
+ }
+ if (\is_array($to) || $to instanceof \Closure) {
+ $replace = 'preg_replace_callback';
+ $to = static function (array $m) use($to) : string {
+ $to = $to($m);
+ if ('' !== $to && (!\is_string($to) || !\preg_match('//u', $to))) {
+ throw new InvalidArgumentException('Replace callback must return a valid UTF-8 string.');
+ }
+ return $to;
+ };
+ } elseif ('' !== $to && !\preg_match('//u', $to)) {
+ throw new InvalidArgumentException('Invalid UTF-8 string.');
+ } else {
+ $replace = 'preg_replace';
+ }
+ \set_error_handler(static function ($t, $m) {
+ throw new InvalidArgumentException($m);
+ });
+ try {
+ if (null === ($string = $replace($fromRegexp . 'u', $to, $this->string))) {
+ $lastError = \preg_last_error();
+ foreach (\get_defined_constants(\true)['pcre'] as $k => $v) {
+ if ($lastError === $v && \substr_compare($k, '_ERROR', -\strlen('_ERROR')) === 0) {
+ throw new RuntimeException('Matching failed with ' . $k . '.');
+ }
+ }
+ throw new RuntimeException('Matching failed with unknown error code.');
+ }
+ } finally {
+ \restore_error_handler();
+ }
+ $str = clone $this;
+ $str->string = $string;
+ return $str;
+ }
+ /**
+ * @return $this
+ */
+ public function reverse()
+ {
+ $str = clone $this;
+ $str->string = \implode('', \array_reverse(\preg_split('/(\\X)/u', $str->string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY)));
+ return $str;
+ }
+ /**
+ * @return $this
+ */
+ public function snake()
+ {
+ $str = $this->camel();
+ $str->string = \mb_strtolower(\preg_replace(['/(\\p{Lu}+)(\\p{Lu}\\p{Ll})/u', '/([\\p{Ll}0-9])(\\p{Lu})/u'], 'ClassLeak202307\\1_\\2', $str->string), 'UTF-8');
+ return $str;
+ }
+ /**
+ * @return $this
+ */
+ public function title(bool $allWords = \false)
+ {
+ $str = clone $this;
+ $limit = $allWords ? -1 : 1;
+ $str->string = \preg_replace_callback('/\\b./u', static function (array $m) : string {
+ return \mb_convert_case($m[0], \MB_CASE_TITLE, 'UTF-8');
+ }, $str->string, $limit);
+ return $str;
+ }
+ /**
+ * @return $this
+ */
+ public function trim(string $chars = " \t\n\r\x00\v\f ")
+ {
+ if (" \t\n\r\x00\v\f " !== $chars && !\preg_match('//u', $chars)) {
+ throw new InvalidArgumentException('Invalid UTF-8 chars.');
+ }
+ $chars = \preg_quote($chars);
+ $str = clone $this;
+ $str->string = \preg_replace("{^[{$chars}]++|[{$chars}]++\$}uD", '', $str->string);
+ return $str;
+ }
+ /**
+ * @return $this
+ */
+ public function trimEnd(string $chars = " \t\n\r\x00\v\f ")
+ {
+ if (" \t\n\r\x00\v\f " !== $chars && !\preg_match('//u', $chars)) {
+ throw new InvalidArgumentException('Invalid UTF-8 chars.');
+ }
+ $chars = \preg_quote($chars);
+ $str = clone $this;
+ $str->string = \preg_replace("{[{$chars}]++\$}uD", '', $str->string);
+ return $str;
+ }
+ /**
+ * @return $this
+ */
+ public function trimPrefix($prefix)
+ {
+ if (!$this->ignoreCase) {
+ return parent::trimPrefix($prefix);
+ }
+ $str = clone $this;
+ if ($prefix instanceof \Traversable) {
+ $prefix = \iterator_to_array($prefix, \false);
+ } elseif ($prefix instanceof parent) {
+ $prefix = $prefix->string;
+ }
+ $prefix = \implode('|', \array_map('preg_quote', (array) $prefix));
+ $str->string = \preg_replace("{^(?:{$prefix})}iuD", '', $this->string);
+ return $str;
+ }
+ /**
+ * @return $this
+ */
+ public function trimStart(string $chars = " \t\n\r\x00\v\f ")
+ {
+ if (" \t\n\r\x00\v\f " !== $chars && !\preg_match('//u', $chars)) {
+ throw new InvalidArgumentException('Invalid UTF-8 chars.');
+ }
+ $chars = \preg_quote($chars);
+ $str = clone $this;
+ $str->string = \preg_replace("{^[{$chars}]++}uD", '', $str->string);
+ return $str;
+ }
+ /**
+ * @return $this
+ */
+ public function trimSuffix($suffix)
+ {
+ if (!$this->ignoreCase) {
+ return parent::trimSuffix($suffix);
+ }
+ $str = clone $this;
+ if ($suffix instanceof \Traversable) {
+ $suffix = \iterator_to_array($suffix, \false);
+ } elseif ($suffix instanceof parent) {
+ $suffix = $suffix->string;
+ }
+ $suffix = \implode('|', \array_map('preg_quote', (array) $suffix));
+ $str->string = \preg_replace("{(?:{$suffix})\$}iuD", '', $this->string);
+ return $str;
+ }
+ /**
+ * @return $this
+ */
+ public function upper()
+ {
+ $str = clone $this;
+ $str->string = \mb_strtoupper($str->string, 'UTF-8');
+ return $str;
+ }
+ public function width(bool $ignoreAnsiDecoration = \true) : int
+ {
+ $width = 0;
+ $s = \str_replace(["\x00", "\x05", "\x07"], '', $this->string);
+ if (\strpos($s, "\r") !== \false) {
+ $s = \str_replace(["\r\n", "\r"], "\n", $s);
+ }
+ if (!$ignoreAnsiDecoration) {
+ $s = \preg_replace('/[\\p{Cc}\\x7F]++/u', '', $s);
+ }
+ foreach (\explode("\n", $s) as $s) {
+ if ($ignoreAnsiDecoration) {
+ $s = \preg_replace('/(?:\\x1B(?:
+ \\[ [\\x30-\\x3F]*+ [\\x20-\\x2F]*+ [\\x40-\\x7E]
+ | [P\\]X^_] .*? \\x1B\\\\
+ | [\\x41-\\x7E]
+ )|[\\p{Cc}\\x7F]++)/xu', '', $s);
+ }
+ $lineWidth = $this->wcswidth($s);
+ if ($lineWidth > $width) {
+ $width = $lineWidth;
+ }
+ }
+ return $width;
+ }
+ /**
+ * @return $this
+ */
+ private function pad(int $len, self $pad, int $type)
+ {
+ $sLen = $this->length();
+ if ($len <= $sLen) {
+ return clone $this;
+ }
+ $padLen = $pad->length();
+ $freeLen = $len - $sLen;
+ $len = $freeLen % $padLen;
+ switch ($type) {
+ case \STR_PAD_RIGHT:
+ return $this->append(\str_repeat($pad->string, \intdiv($freeLen, $padLen)) . ($len ? $pad->slice(0, $len) : ''));
+ case \STR_PAD_LEFT:
+ return $this->prepend(\str_repeat($pad->string, \intdiv($freeLen, $padLen)) . ($len ? $pad->slice(0, $len) : ''));
+ case \STR_PAD_BOTH:
+ $freeLen /= 2;
+ $rightLen = \ceil($freeLen);
+ $len = $rightLen % $padLen;
+ $str = $this->append(\str_repeat($pad->string, \intdiv($rightLen, $padLen)) . ($len ? $pad->slice(0, $len) : ''));
+ $leftLen = \floor($freeLen);
+ $len = $leftLen % $padLen;
+ return $str->prepend(\str_repeat($pad->string, \intdiv($leftLen, $padLen)) . ($len ? $pad->slice(0, $len) : ''));
+ default:
+ throw new InvalidArgumentException('Invalid padding type.');
+ }
+ }
+ /**
+ * Based on https://github.com/jquast/wcwidth, a Python implementation of https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c.
+ */
+ private function wcswidth(string $string) : int
+ {
+ $width = 0;
+ foreach (\preg_split('//u', $string, -1, \PREG_SPLIT_NO_EMPTY) as $c) {
+ $codePoint = \mb_ord($c, 'UTF-8');
+ if (0 === $codePoint || 0x34f === $codePoint || 0x200b <= $codePoint && 0x200f >= $codePoint || 0x2028 === $codePoint || 0x2029 === $codePoint || 0x202a <= $codePoint && 0x202e >= $codePoint || 0x2060 <= $codePoint && 0x2063 >= $codePoint) {
+ continue;
+ }
+ // Non printable characters
+ if (32 > $codePoint || 0x7f <= $codePoint && 0xa0 > $codePoint) {
+ return -1;
+ }
+ self::$tableZero = self::$tableZero ?? (require __DIR__ . '/Resources/data/wcswidth_table_zero.php');
+ if ($codePoint >= self::$tableZero[0][0] && $codePoint <= self::$tableZero[$ubound = \count(self::$tableZero) - 1][1]) {
+ $lbound = 0;
+ while ($ubound >= $lbound) {
+ $mid = \floor(($lbound + $ubound) / 2);
+ if ($codePoint > self::$tableZero[$mid][1]) {
+ $lbound = $mid + 1;
+ } elseif ($codePoint < self::$tableZero[$mid][0]) {
+ $ubound = $mid - 1;
+ } else {
+ continue 2;
+ }
+ }
+ }
+ self::$tableWide = self::$tableWide ?? (require __DIR__ . '/Resources/data/wcswidth_table_wide.php');
+ if ($codePoint >= self::$tableWide[0][0] && $codePoint <= self::$tableWide[$ubound = \count(self::$tableWide) - 1][1]) {
+ $lbound = 0;
+ while ($ubound >= $lbound) {
+ $mid = \floor(($lbound + $ubound) / 2);
+ if ($codePoint > self::$tableWide[$mid][1]) {
+ $lbound = $mid + 1;
+ } elseif ($codePoint < self::$tableWide[$mid][0]) {
+ $ubound = $mid - 1;
+ } else {
+ $width += 2;
+ continue 2;
+ }
+ }
+ }
+ ++$width;
+ }
+ return $width;
+ }
+}
diff --git a/vendor/symfony/string/ByteString.php b/vendor/symfony/string/ByteString.php
new file mode 100644
index 00000000..5321ec86
--- /dev/null
+++ b/vendor/symfony/string/ByteString.php
@@ -0,0 +1,459 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\String;
+
+use ClassLeak202307\Symfony\Component\String\Exception\ExceptionInterface;
+use ClassLeak202307\Symfony\Component\String\Exception\InvalidArgumentException;
+use ClassLeak202307\Symfony\Component\String\Exception\RuntimeException;
+/**
+ * Represents a binary-safe string of bytes.
+ *
+ * @author Nicolas Grekas
+ * @author Hugo Hamon
+ *
+ * @throws ExceptionInterface
+ */
+class ByteString extends AbstractString
+{
+ private const ALPHABET_ALPHANUMERIC = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
+ public function __construct(string $string = '')
+ {
+ $this->string = $string;
+ }
+ /*
+ * The following method was derived from code of the Hack Standard Library (v4.40 - 2020-05-03)
+ *
+ * https://github.com/hhvm/hsl/blob/80a42c02f036f72a42f0415e80d6b847f4bf62d5/src/random/private.php#L16
+ *
+ * Code subject to the MIT license (https://github.com/hhvm/hsl/blob/master/LICENSE).
+ *
+ * Copyright (c) 2004-2020, Facebook, Inc. (https://www.facebook.com/)
+ */
+ public static function fromRandom(int $length = 16, string $alphabet = null) : self
+ {
+ if ($length <= 0) {
+ throw new InvalidArgumentException(\sprintf('A strictly positive length is expected, "%d" given.', $length));
+ }
+ $alphabet = $alphabet ?? self::ALPHABET_ALPHANUMERIC;
+ $alphabetSize = \strlen($alphabet);
+ $bits = (int) \ceil(\log($alphabetSize, 2.0));
+ if ($bits <= 0 || $bits > 56) {
+ throw new InvalidArgumentException('The length of the alphabet must in the [2^1, 2^56] range.');
+ }
+ $ret = '';
+ while ($length > 0) {
+ $urandomLength = (int) \ceil(2 * $length * $bits / 8.0);
+ $data = \random_bytes($urandomLength);
+ $unpackedData = 0;
+ $unpackedBits = 0;
+ for ($i = 0; $i < $urandomLength && $length > 0; ++$i) {
+ // Unpack 8 bits
+ $unpackedData = $unpackedData << 8 | \ord($data[$i]);
+ $unpackedBits += 8;
+ // While we have enough bits to select a character from the alphabet, keep
+ // consuming the random data
+ for (; $unpackedBits >= $bits && $length > 0; $unpackedBits -= $bits) {
+ $index = $unpackedData & (1 << $bits) - 1;
+ $unpackedData >>= $bits;
+ // Unfortunately, the alphabet size is not necessarily a power of two.
+ // Worst case, it is 2^k + 1, which means we need (k+1) bits and we
+ // have around a 50% chance of missing as k gets larger
+ if ($index < $alphabetSize) {
+ $ret .= $alphabet[$index];
+ --$length;
+ }
+ }
+ }
+ }
+ return new static($ret);
+ }
+ public function bytesAt(int $offset) : array
+ {
+ $str = $this->string[$offset] ?? '';
+ return '' === $str ? [] : [\ord($str)];
+ }
+ /**
+ * @return $this
+ */
+ public function append(string ...$suffix)
+ {
+ $str = clone $this;
+ $str->string .= 1 >= \count($suffix) ? $suffix[0] ?? '' : \implode('', $suffix);
+ return $str;
+ }
+ /**
+ * @return $this
+ */
+ public function camel()
+ {
+ $str = clone $this;
+ $parts = \explode(' ', \trim(\ucwords(\preg_replace('/[^a-zA-Z0-9\\x7f-\\xff]++/', ' ', $this->string))));
+ $parts[0] = 1 !== \strlen($parts[0]) && \ctype_upper($parts[0]) ? $parts[0] : \lcfirst($parts[0]);
+ $str->string = \implode('', $parts);
+ return $str;
+ }
+ public function chunk(int $length = 1) : array
+ {
+ if (1 > $length) {
+ throw new InvalidArgumentException('The chunk length must be greater than zero.');
+ }
+ if ('' === $this->string) {
+ return [];
+ }
+ $str = clone $this;
+ $chunks = [];
+ foreach (\str_split($this->string, $length) as $chunk) {
+ $str->string = $chunk;
+ $chunks[] = clone $str;
+ }
+ return $chunks;
+ }
+ /**
+ * @param string|mixed[]|\Symfony\Component\String\AbstractString $suffix
+ */
+ public function endsWith($suffix) : bool
+ {
+ if ($suffix instanceof AbstractString) {
+ $suffix = $suffix->string;
+ } elseif (!\is_string($suffix)) {
+ return parent::endsWith($suffix);
+ }
+ return '' !== $suffix && \strlen($this->string) >= \strlen($suffix) && 0 === \substr_compare($this->string, $suffix, -\strlen($suffix), null, $this->ignoreCase);
+ }
+ /**
+ * @param string|mixed[]|\Symfony\Component\String\AbstractString $string
+ */
+ public function equalsTo($string) : bool
+ {
+ if ($string instanceof AbstractString) {
+ $string = $string->string;
+ } elseif (!\is_string($string)) {
+ return parent::equalsTo($string);
+ }
+ if ('' !== $string && $this->ignoreCase) {
+ return 0 === \strcasecmp($string, $this->string);
+ }
+ return $string === $this->string;
+ }
+ /**
+ * @return $this
+ */
+ public function folded()
+ {
+ $str = clone $this;
+ $str->string = \strtolower($str->string);
+ return $str;
+ }
+ /**
+ * @param string|mixed[]|\Symfony\Component\String\AbstractString $needle
+ */
+ public function indexOf($needle, int $offset = 0) : ?int
+ {
+ if ($needle instanceof AbstractString) {
+ $needle = $needle->string;
+ } elseif (!\is_string($needle)) {
+ return parent::indexOf($needle, $offset);
+ }
+ if ('' === $needle) {
+ return null;
+ }
+ $i = $this->ignoreCase ? \stripos($this->string, $needle, $offset) : \strpos($this->string, $needle, $offset);
+ return \false === $i ? null : $i;
+ }
+ /**
+ * @param string|mixed[]|\Symfony\Component\String\AbstractString $needle
+ */
+ public function indexOfLast($needle, int $offset = 0) : ?int
+ {
+ if ($needle instanceof AbstractString) {
+ $needle = $needle->string;
+ } elseif (!\is_string($needle)) {
+ return parent::indexOfLast($needle, $offset);
+ }
+ if ('' === $needle) {
+ return null;
+ }
+ $i = $this->ignoreCase ? \strripos($this->string, $needle, $offset) : \strrpos($this->string, $needle, $offset);
+ return \false === $i ? null : $i;
+ }
+ public function isUtf8() : bool
+ {
+ return '' === $this->string || \preg_match('//u', $this->string);
+ }
+ /**
+ * @return $this
+ */
+ public function join(array $strings, string $lastGlue = null)
+ {
+ $str = clone $this;
+ $tail = null !== $lastGlue && 1 < \count($strings) ? $lastGlue . \array_pop($strings) : '';
+ $str->string = \implode($this->string, $strings) . $tail;
+ return $str;
+ }
+ public function length() : int
+ {
+ return \strlen($this->string);
+ }
+ /**
+ * @return $this
+ */
+ public function lower()
+ {
+ $str = clone $this;
+ $str->string = \strtolower($str->string);
+ return $str;
+ }
+ public function match(string $regexp, int $flags = 0, int $offset = 0) : array
+ {
+ $match = (\PREG_PATTERN_ORDER | \PREG_SET_ORDER) & $flags ? 'preg_match_all' : 'preg_match';
+ if ($this->ignoreCase) {
+ $regexp .= 'i';
+ }
+ \set_error_handler(static function ($t, $m) {
+ throw new InvalidArgumentException($m);
+ });
+ try {
+ if (\false === $match($regexp, $this->string, $matches, $flags | \PREG_UNMATCHED_AS_NULL, $offset)) {
+ throw new RuntimeException('Matching failed with error: ' . \preg_last_error_msg());
+ }
+ } finally {
+ \restore_error_handler();
+ }
+ return $matches;
+ }
+ /**
+ * @return $this
+ */
+ public function padBoth(int $length, string $padStr = ' ')
+ {
+ $str = clone $this;
+ $str->string = \str_pad($this->string, $length, $padStr, \STR_PAD_BOTH);
+ return $str;
+ }
+ /**
+ * @return $this
+ */
+ public function padEnd(int $length, string $padStr = ' ')
+ {
+ $str = clone $this;
+ $str->string = \str_pad($this->string, $length, $padStr, \STR_PAD_RIGHT);
+ return $str;
+ }
+ /**
+ * @return $this
+ */
+ public function padStart(int $length, string $padStr = ' ')
+ {
+ $str = clone $this;
+ $str->string = \str_pad($this->string, $length, $padStr, \STR_PAD_LEFT);
+ return $str;
+ }
+ /**
+ * @return $this
+ */
+ public function prepend(string ...$prefix)
+ {
+ $str = clone $this;
+ $str->string = (1 >= \count($prefix) ? $prefix[0] ?? '' : \implode('', $prefix)) . $str->string;
+ return $str;
+ }
+ /**
+ * @return $this
+ */
+ public function replace(string $from, string $to)
+ {
+ $str = clone $this;
+ if ('' !== $from) {
+ $str->string = $this->ignoreCase ? \str_ireplace($from, $to, $this->string) : \str_replace($from, $to, $this->string);
+ }
+ return $str;
+ }
+ /**
+ * @param string|callable $to
+ * @return $this
+ */
+ public function replaceMatches(string $fromRegexp, $to)
+ {
+ if ($this->ignoreCase) {
+ $fromRegexp .= 'i';
+ }
+ $replace = \is_array($to) || $to instanceof \Closure ? 'preg_replace_callback' : 'preg_replace';
+ \set_error_handler(static function ($t, $m) {
+ throw new InvalidArgumentException($m);
+ });
+ try {
+ if (null === ($string = $replace($fromRegexp, $to, $this->string))) {
+ $lastError = \preg_last_error();
+ foreach (\get_defined_constants(\true)['pcre'] as $k => $v) {
+ if ($lastError === $v && \substr_compare($k, '_ERROR', -\strlen('_ERROR')) === 0) {
+ throw new RuntimeException('Matching failed with ' . $k . '.');
+ }
+ }
+ throw new RuntimeException('Matching failed with unknown error code.');
+ }
+ } finally {
+ \restore_error_handler();
+ }
+ $str = clone $this;
+ $str->string = $string;
+ return $str;
+ }
+ /**
+ * @return $this
+ */
+ public function reverse()
+ {
+ $str = clone $this;
+ $str->string = \strrev($str->string);
+ return $str;
+ }
+ /**
+ * @return $this
+ */
+ public function slice(int $start = 0, int $length = null)
+ {
+ $str = clone $this;
+ $str->string = (string) \substr($this->string, $start, $length ?? \PHP_INT_MAX);
+ return $str;
+ }
+ /**
+ * @return $this
+ */
+ public function snake()
+ {
+ $str = $this->camel();
+ $str->string = \strtolower(\preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\\d])([A-Z])/'], 'ClassLeak202307\\1_\\2', $str->string));
+ return $str;
+ }
+ /**
+ * @return $this
+ */
+ public function splice(string $replacement, int $start = 0, int $length = null)
+ {
+ $str = clone $this;
+ $str->string = \substr_replace($this->string, $replacement, $start, $length ?? \PHP_INT_MAX);
+ return $str;
+ }
+ public function split(string $delimiter, int $limit = null, int $flags = null) : array
+ {
+ if (1 > ($limit = $limit ?? \PHP_INT_MAX)) {
+ throw new InvalidArgumentException('Split limit must be a positive integer.');
+ }
+ if ('' === $delimiter) {
+ throw new InvalidArgumentException('Split delimiter is empty.');
+ }
+ if (null !== $flags) {
+ return parent::split($delimiter, $limit, $flags);
+ }
+ $str = clone $this;
+ $chunks = $this->ignoreCase ? \preg_split('{' . \preg_quote($delimiter) . '}iD', $this->string, $limit) : \explode($delimiter, $this->string, $limit);
+ foreach ($chunks as &$chunk) {
+ $str->string = $chunk;
+ $chunk = clone $str;
+ }
+ return $chunks;
+ }
+ /**
+ * @param string|mixed[]|\Symfony\Component\String\AbstractString $prefix
+ */
+ public function startsWith($prefix) : bool
+ {
+ if ($prefix instanceof AbstractString) {
+ $prefix = $prefix->string;
+ } elseif (!\is_string($prefix)) {
+ return parent::startsWith($prefix);
+ }
+ return '' !== $prefix && 0 === ($this->ignoreCase ? \strncasecmp($this->string, $prefix, \strlen($prefix)) : \strncmp($this->string, $prefix, \strlen($prefix)));
+ }
+ /**
+ * @return $this
+ */
+ public function title(bool $allWords = \false)
+ {
+ $str = clone $this;
+ $str->string = $allWords ? \ucwords($str->string) : \ucfirst($str->string);
+ return $str;
+ }
+ public function toUnicodeString(string $fromEncoding = null) : UnicodeString
+ {
+ return new UnicodeString($this->toCodePointString($fromEncoding)->string);
+ }
+ public function toCodePointString(string $fromEncoding = null) : CodePointString
+ {
+ $u = new CodePointString();
+ if (\in_array($fromEncoding, [null, 'utf8', 'utf-8', 'UTF8', 'UTF-8'], \true) && \preg_match('//u', $this->string)) {
+ $u->string = $this->string;
+ return $u;
+ }
+ \set_error_handler(static function ($t, $m) {
+ throw new InvalidArgumentException($m);
+ });
+ try {
+ try {
+ $validEncoding = \false !== \mb_detect_encoding($this->string, $fromEncoding ?? 'Windows-1252', \true);
+ } catch (InvalidArgumentException $e) {
+ if (!\function_exists('iconv')) {
+ throw $e;
+ }
+ $u->string = \iconv($fromEncoding ?? 'Windows-1252', 'UTF-8', $this->string);
+ return $u;
+ }
+ } finally {
+ \restore_error_handler();
+ }
+ if (!$validEncoding) {
+ throw new InvalidArgumentException(\sprintf('Invalid "%s" string.', $fromEncoding ?? 'Windows-1252'));
+ }
+ $u->string = \mb_convert_encoding($this->string, 'UTF-8', $fromEncoding ?? 'Windows-1252');
+ return $u;
+ }
+ /**
+ * @return $this
+ */
+ public function trim(string $chars = " \t\n\r\x00\v\f")
+ {
+ $str = clone $this;
+ $str->string = \trim($str->string, $chars);
+ return $str;
+ }
+ /**
+ * @return $this
+ */
+ public function trimEnd(string $chars = " \t\n\r\x00\v\f")
+ {
+ $str = clone $this;
+ $str->string = \rtrim($str->string, $chars);
+ return $str;
+ }
+ /**
+ * @return $this
+ */
+ public function trimStart(string $chars = " \t\n\r\x00\v\f")
+ {
+ $str = clone $this;
+ $str->string = \ltrim($str->string, $chars);
+ return $str;
+ }
+ /**
+ * @return $this
+ */
+ public function upper()
+ {
+ $str = clone $this;
+ $str->string = \strtoupper($str->string);
+ return $str;
+ }
+ public function width(bool $ignoreAnsiDecoration = \true) : int
+ {
+ $string = \preg_match('//u', $this->string) ? $this->string : \preg_replace('/[\\x80-\\xFF]/', '?', $this->string);
+ return (new CodePointString($string))->width($ignoreAnsiDecoration);
+ }
+}
diff --git a/vendor/symfony/string/CHANGELOG.md b/vendor/symfony/string/CHANGELOG.md
new file mode 100644
index 00000000..31a3b54d
--- /dev/null
+++ b/vendor/symfony/string/CHANGELOG.md
@@ -0,0 +1,40 @@
+CHANGELOG
+=========
+
+6.2
+---
+
+ * Add support for emoji in `AsciiSlugger`
+
+5.4
+---
+
+ * Add `trimSuffix()` and `trimPrefix()` methods
+
+5.3
+---
+
+ * Made `AsciiSlugger` fallback to parent locale's symbolsMap
+
+5.2.0
+-----
+
+ * added a `FrenchInflector` class
+
+5.1.0
+-----
+
+ * added the `AbstractString::reverse()` method
+ * made `AbstractString::width()` follow POSIX.1-2001
+ * added `LazyString` which provides memoizing stringable objects
+ * The component is not marked as `@experimental` anymore
+ * added the `s()` helper method to get either an `UnicodeString` or `ByteString` instance,
+ depending of the input string UTF-8 compliancy
+ * added `$cut` parameter to `Symfony\Component\String\AbstractString::truncate()`
+ * added `AbstractString::containsAny()`
+ * allow passing a string of custom characters to `ByteString::fromRandom()`
+
+5.0.0
+-----
+
+ * added the component as experimental
diff --git a/vendor/symfony/string/CodePointString.php b/vendor/symfony/string/CodePointString.php
new file mode 100644
index 00000000..a0b3fc00
--- /dev/null
+++ b/vendor/symfony/string/CodePointString.php
@@ -0,0 +1,234 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace ClassLeak202307\Symfony\Component\String;
+
+use ClassLeak202307\Symfony\Component\String\Exception\ExceptionInterface;
+use ClassLeak202307\Symfony\Component\String\Exception\InvalidArgumentException;
+/**
+ * Represents a string of Unicode code points encoded as UTF-8.
+ *
+ * @author Nicolas Grekas