Import latest app updates from streamline

An updated set of source files and initialization was provided by streamline to
address issues observed during initial testing. These files have been updated in
order to generate a new set of app images.
This commit is contained in:
2024-04-11 11:16:51 -07:00
parent cb4c6b4c1a
commit 4a89356390
10435 changed files with 107737 additions and 1220538 deletions
@@ -1,139 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Console\Descriptor;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\CommandNotFoundException;
/**
* @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
*
* @internal
*/
class ApplicationDescription
{
public const GLOBAL_NAMESPACE = '_global';
private Application $application;
private ?string $namespace;
private bool $showHidden;
private array $namespaces;
/**
* @var array<string, Command>
*/
private array $commands;
/**
* @var array<string, Command>
*/
private array $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;
}
}
@@ -1,74 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Console\Descriptor;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
* @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
*
* @internal
*/
abstract class Descriptor implements DescriptorInterface
{
protected OutputInterface $output;
public function describe(OutputInterface $output, object $object, array $options = []): void
{
$this->output = $output;
match (true) {
$object instanceof InputArgument => $this->describeInputArgument($object, $options),
$object instanceof InputOption => $this->describeInputOption($object, $options),
$object instanceof InputDefinition => $this->describeInputDefinition($object, $options),
$object instanceof Command => $this->describeCommand($object, $options),
$object instanceof Application => $this->describeApplication($object, $options),
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.
*/
abstract protected function describeInputArgument(InputArgument $argument, array $options = []): void;
/**
* Describes an InputOption instance.
*/
abstract protected function describeInputOption(InputOption $option, array $options = []): void;
/**
* Describes an InputDefinition instance.
*/
abstract protected function describeInputDefinition(InputDefinition $definition, array $options = []): void;
/**
* Describes a Command instance.
*/
abstract protected function describeCommand(Command $command, array $options = []): void;
/**
* Describes an Application instance.
*/
abstract protected function describeApplication(Application $application, array $options = []): void;
}
@@ -1,27 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Console\Descriptor;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Descriptor interface.
*
* @author Jean-François Simon <contact@jfsimon.fr>
*/
interface DescriptorInterface
{
/**
* @return void
*/
public function describe(OutputInterface $output, object $object, array $options = []);
}
@@ -1,166 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Console\Descriptor;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
/**
* JSON descriptor.
*
* @author Jean-François Simon <contact@jfsimon.fr>
*
* @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;
}
}
@@ -1,173 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Console\Descriptor;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\Helper;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Markdown descriptor.
*
* @author Jean-François Simon <contact@jfsimon.fr>
*
* @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() ?: '<none>')."`\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(), fn ($carry, $usage) => $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()), fn ($carry, $usage) => $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(fn ($commandName) => 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';
}
}
@@ -1,272 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Console\Descriptor;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\Helper;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\String\UnicodeString;
class ReStructuredTextDescriptor extends Descriptor
{
// <h1>
private string $partChar = '=';
// <h2>
private string $chapterChar = '-';
// <h3>
private string $sectionChar = '~';
// <h4>
private string $subsectionChar = '.';
// <h5>
private string $subsubsectionChar = '^';
// <h6>
private string $paragraphsChar = '"';
private array $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() ?: '<none>'."\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 fn ($carry, $usage) => $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 fn ($carry, $usage) => $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 fn ($commandName) => 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) {
}
$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;
}
}
@@ -1,317 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Console\Descriptor;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Formatter\OutputFormatter;
use Symfony\Component\Console\Helper\Helper;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
/**
* Text descriptor.
*
* @author Jean-François Simon <contact@jfsimon.fr>
*
* @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('<comment> [default: %s]</comment>', $this->formatDefaultValue($argument->getDefault()));
} else {
$default = '';
}
$totalWidth = $options['total_width'] ?? Helper::width($argument->getName());
$spacingWidth = $totalWidth - \strlen($argument->getName());
$this->writeText(sprintf(' <info>%s</info> %s%s%s',
$argument->getName(),
str_repeat(' ', $spacingWidth),
// + 4 = 2 spaces before <info>, 2 spaces after </info>
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('<comment> [default: %s]</comment>', $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(' <info>%s</info> %s%s%s%s',
$synopsis,
str_repeat(' ', $spacingWidth),
// + 4 = 2 spaces before <info>, 2 spaces after </info>
preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $option->getDescription()),
$default,
$option->isArray() ? '<comment> (multiple values allowed)</comment>' : ''
), $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('<comment>Arguments:</comment>', $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('<comment>Options:</comment>', $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('<comment>Description:</comment>', $options);
$this->writeText("\n");
$this->writeText(' '.$description);
$this->writeText("\n\n");
}
$this->writeText('<comment>Usage:</comment>', $options);
foreach (array_merge([$command->getSynopsis(true)], $command->getAliases(), $command->getUsages()) as $usage) {
$this->writeText("\n");
$this->writeText(' '.OutputFormatter::escape($usage), $options);
}
$this->writeText("\n");
$definition = $command->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('<comment>Help:</comment>', $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("<comment>Usage:</comment>\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(fn ($namespace) => array_intersect($namespace['commands'], array_keys($commands)), array_values($namespaces)))));
if ($describedNamespace) {
$this->writeText(sprintf('<comment>Available commands for the "%s" namespace:</comment>', $describedNamespace), $options);
} else {
$this->writeText('<comment>Available commands:</comment>', $options);
}
foreach ($namespaces as $namespace) {
$namespace['commands'] = array_filter($namespace['commands'], fn ($name) => isset($commands[$name]));
if (!$namespace['commands']) {
continue;
}
if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
$this->writeText("\n");
$this->writeText(' <comment>'.$namespace['id'].'</comment>', $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(' <info>%s</info>%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.
*/
private function formatDefaultValue(mixed $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<Command|string> $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;
}
}
@@ -1,232 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Console\Descriptor;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
/**
* XML descriptor.
*
* @author Jean-François Simon <contact@jfsimon.fr>
*
* @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;
}
}