Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[Console] Support binary / negatable options #26292

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions 3 src/Symfony/Component/Console/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -949,8 +949,7 @@ protected function getDefaultInputDefinition()
new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'),
new InputOption('--verbose', '-v|vv|vvv', InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'),
new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version'),
new InputOption('--ansi', '', InputOption::VALUE_NONE, 'Force ANSI output'),
new InputOption('--no-ansi', '', InputOption::VALUE_NONE, 'Disable ANSI output'),
new InputOption('--ansi', '', InputOption::VALUE_BINARY, 'Force ANSI output', null),
new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question'),
));
}
Expand Down
4 changes: 4 additions & 0 deletions 4 src/Symfony/Component/Console/Descriptor/JsonDescriptor.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ private function getInputOptionData(InputOption $option)
'accept_value' => $option->acceptValue(),
'is_value_required' => $option->isValueRequired(),
'is_multiple' => $option->isArray(),
'is_negatable' => $option->isNegatable(),
'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $option->getDescription()),
'default' => INF === $option->getDefault() ? 'INF' : $option->getDefault(),
);
Expand All @@ -142,6 +143,9 @@ private function getInputDefinitionData(InputDefinition $definition)

$inputOptions = array();
foreach ($definition->getOptions() as $name => $option) {
if ($option->isHidden()) {
continue;
}
$inputOptions[$name] = $this->getInputOptionData($option);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ protected function describeInputArgument(InputArgument $argument, array $options
*/
protected function describeInputOption(InputOption $option, array $options = array())
{
$name = '--'.$option->getName();
$negatable = $option->isNegatable() ? '[no-]' : '';
$name = '--'.$negatable.$option->getName();
if ($option->getShortcut()) {
$name .= '|-'.implode('|-', explode('|', $option->getShortcut())).'';
}
Expand All @@ -79,6 +80,7 @@ protected function describeInputOption(InputOption $option, array $options = arr
.'* 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)).'`'
);
}
Expand All @@ -103,6 +105,9 @@ protected function describeInputDefinition(InputDefinition $definition, array $o

$this->write('### Options');
foreach ($definition->getOptions() as $option) {
if ($option->isHidden()) {
continue;
}
$this->write("\n\n");
$this->write($this->describeInputOption($option));
}
Expand Down
12 changes: 9 additions & 3 deletions 12 src/Symfony/Component/Console/Descriptor/TextDescriptor.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,12 @@ protected function describeInputArgument(InputArgument $argument, array $options
*/
protected function describeInputOption(InputOption $option, array $options = array())
{
$default = '';
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 = '';
} elseif ($option->isNegatable() && (null !== $option->getDefault())) {
$negative_default = $option->getDefault() ? '' : 'no-';
$default = sprintf('<comment> [default: --%s%s]</comment>', $negative_default, $option->getName());
}

$value = '';
Expand All @@ -72,9 +74,10 @@ protected function describeInputOption(InputOption $option, array $options = arr
}

$totalWidth = isset($options['total_width']) ? $options['total_width'] : $this->calculateTotalWidthForOptions(array($option));
$negatable = $option->isNegatable() ? '[no-]' : '';
$synopsis = sprintf('%s%s',
$option->getShortcut() ? sprintf('-%s, ', $option->getShortcut()) : ' ',
sprintf('--%s%s', $option->getName(), $value)
sprintf('--%s%s%s', $negatable, $option->getName(), $value)
);

$spacingWidth = $totalWidth - Helper::strlen($synopsis);
Expand Down Expand Up @@ -117,6 +120,9 @@ protected function describeInputDefinition(InputDefinition $definition, array $o

$this->writeText('<comment>Options:</comment>', $options);
foreach ($definition->getOptions() as $option) {
if ($option->isHidden()) {
continue;
}
if (strlen($option->getShortcut()) > 1) {
$laterOptions[] = $option;
continue;
Expand Down
5 changes: 4 additions & 1 deletion 5 src/Symfony/Component/Console/Descriptor/XmlDescriptor.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ public function getInputDefinitionDocument(InputDefinition $definition)

$definitionXML->appendChild($optionsXML = $dom->createElement('options'));
foreach ($definition->getOptions() as $option) {
$this->appendDocument($optionsXML, $this->getInputOptionDocument($option));
if (!$option->isHidden()) {
$this->appendDocument($optionsXML, $this->getInputOptionDocument($option));
}
}

return $dom;
Expand Down Expand Up @@ -225,6 +227,7 @@ private function getInputOptionDocument(InputOption $option): \DOMDocument
$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->setAttribute('is_negatable', $option->isNegatable() ? 1 : 0);
$objectXML->appendChild($descriptionXML = $dom->createElement('description'));
$descriptionXML->appendChild($dom->createTextNode($option->getDescription()));

Expand Down
17 changes: 3 additions & 14 deletions 17 src/Symfony/Component/Console/Input/ArgvInput.php
Original file line number Diff line number Diff line change
Expand Up @@ -213,11 +213,7 @@ private function addShortOption($shortcut, $value)
*/
private function addLongOption($name, $value)
{
if (!$this->definition->hasOption($name)) {
throw new RuntimeException(sprintf('The "--%s" option does not exist.', $name));
}

$option = $this->definition->getOption($name);
$option = $this->getOptionDefinition($name);

if (null !== $value && !$option->acceptValue()) {
throw new RuntimeException(sprintf('The "--%s" option does not accept a value.', $name));
Expand All @@ -234,15 +230,8 @@ private function addLongOption($name, $value)
}
}

if (null === $value) {
if ($option->isValueRequired()) {
throw new RuntimeException(sprintf('The "--%s" option requires a value.', $name));
}

if (!$option->isArray() && !$option->isValueOptional()) {
$value = true;
}
}
$name = $option->effectiveName();
$value = $option->checkValue($value);

if ($option->isArray()) {
$this->options[$name][] = $value;
Expand Down
18 changes: 1 addition & 17 deletions 18 src/Symfony/Component/Console/Input/ArrayInput.php
Original file line number Diff line number Diff line change
Expand Up @@ -168,23 +168,7 @@ private function addShortOption($shortcut, $value)
*/
private function addLongOption($name, $value)
{
if (!$this->definition->hasOption($name)) {
throw new InvalidOptionException(sprintf('The "--%s" option does not exist.', $name));
}

$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;
$this->setOption($name, $value);
}

/**
Expand Down
30 changes: 20 additions & 10 deletions 30 src/Symfony/Component/Console/Input/Input.php
Original file line number Diff line number Diff line change
Expand Up @@ -146,23 +146,17 @@ public function getOptions()
*/
public function getOption($name)
{
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();
$option = $this->getOptionDefinition($name);
return array_key_exists($name, $this->options) ? $this->options[$name] : $option->getDefault();
}

/**
* {@inheritdoc}
*/
public function setOption($name, $value)
{
if (!$this->definition->hasOption($name)) {
throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
}

$this->options[$name] = $value;
$option = $this->getOptionDefinition($name);
$this->options[$option->effectiveName()] = $option->checkValue($value);
}

/**
Expand Down Expand Up @@ -200,4 +194,20 @@ public function getStream()
{
return $this->stream;
}

/**
* Look up the option definition for the given option name.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks

*
* @param string $name
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As this would target 4.4, you can use type hints instead of phpdocs.

*
* @return InputOption
*/
protected function getOptionDefinition($name)
{
if (!$this->definition->hasOption($name)) {
throw new RuntimeException(sprintf('The "--%s" option does not exist.', $name));
}

return $this->definition->getOption($name);
}
}
18 changes: 17 additions & 1 deletion 18 src/Symfony/Component/Console/Input/InputDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,19 @@ public function addOptions($options = array())
* @throws LogicException When option given already exist
*/
public function addOption(InputOption $option)
{
$this->doAddOption($option);

if ($option->isNegatable()) {
$negatedOption = new NegatedInputOption($option);
$this->doAddOption($negatedOption);
}
}

/**
* @throws LogicException When option given already exist
*/
private function doAddOption(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()));
Expand Down Expand Up @@ -324,7 +337,7 @@ public function getOptionDefaults()
{
$values = array();
foreach ($this->options as $option) {
$values[$option->getName()] = $option->getDefault();
$values[$option->effectiveName()] = $option->getDefault();
}

return $values;
Expand Down Expand Up @@ -363,6 +376,9 @@ public function getSynopsis($short = false)
$elements[] = '[options]';
} elseif (!$short) {
foreach ($this->getOptions() as $option) {
if ($option->isHidden()) {
continue;
}
$value = '';
if ($option->acceptValue()) {
$value = sprintf(
Expand Down
71 changes: 68 additions & 3 deletions 71 src/Symfony/Component/Console/Input/InputOption.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
namespace Symfony\Component\Console\Input;

use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\InvalidOptionException;
use Symfony\Component\Console\Exception\LogicException;

/**
Expand All @@ -25,6 +26,9 @@ class InputOption
const VALUE_REQUIRED = 2;
const VALUE_OPTIONAL = 4;
const VALUE_IS_ARRAY = 8;
const VALUE_NEGATABLE = 16;
const VALUE_HIDDEN = 32;
const VALUE_BINARY = (self::VALUE_NONE | self::VALUE_NEGATABLE);

private $name;
private $shortcut;
Expand Down Expand Up @@ -70,7 +74,7 @@ public function __construct(string $name, $shortcut = null, int $mode = null, st

if (null === $mode) {
$mode = self::VALUE_NONE;
} elseif ($mode > 15 || $mode < 1) {
} elseif ($mode >= (self::VALUE_HIDDEN << 1) || $mode < 1) {
throw new InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode));
}

Expand Down Expand Up @@ -106,6 +110,11 @@ public function getName()
return $this->name;
}

public function effectiveName()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably be getEffectiveName() instead.

{
return $this->getName();
}

/**
* Returns true if the option accepts a value.
*
Expand Down Expand Up @@ -146,6 +155,39 @@ public function isArray()
return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode);
}

/**
* Returns true if the option is negatable (option --foo can be forced
* to 'false' via the --no-foo option).
*
* @return bool true if mode is self::VALUE_NEGATABLE, false otherwise
*/
public function isNegatable()
{
return self::VALUE_NEGATABLE === (self::VALUE_NEGATABLE & $this->mode);
}

/**
* Returns true if the option should not be shown in help (e.g. a negated
* option).
*
* @return bool true if mode is self::VALUE_HIDDEN, false otherwise
*/
public function isHidden()
{
return self::VALUE_HIDDEN === (self::VALUE_HIDDEN & $this->mode);
}

/**
* Returns true if the option is binary (can be --foo or --no-foo, and
* nothing else).
*
* @return bool true if negatable and does not have a value.
*/
public function isBinary()
{
return $this->isNegatable() && !$this->acceptValue();
}

/**
* Sets the default value.
*
Expand All @@ -155,7 +197,7 @@ public function isArray()
*/
public function setDefault($default = null)
{
if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) {
if (self::VALUE_NONE === ((self::VALUE_NONE | self::VALUE_NEGATABLE) & $this->mode) && null !== $default) {
throw new LogicException('Cannot set a default value when using InputOption::VALUE_NONE mode.');
}

Expand All @@ -167,7 +209,7 @@ public function setDefault($default = null)
}
}

$this->default = $this->acceptValue() ? $default : false;
$this->default = ($this->acceptValue() || $this->isNegatable()) ? $default : false;
}

/**
Expand All @@ -190,6 +232,27 @@ public function getDescription()
return $this->description;
}

/**
* Checks the validity of a value, and alters it as necessary
*
* @param mixed $value
*
* @return @mixed
*/
public function checkValue($value)
{
if (null === $value) {
if ($this->isValueRequired()) {
throw new InvalidOptionException(sprintf('The "--%s" option requires a value.', $this->getName()));
}

if (!$this->isValueOptional()) {
return true;
}
}
return $value;
}

/**
* Checks whether the given option equals this one.
*
Expand All @@ -200,6 +263,8 @@ public function equals(InputOption $option)
return $option->getName() === $this->getName()
&& $option->getShortcut() === $this->getShortcut()
&& $option->getDefault() === $this->getDefault()
&& $option->isHidden() === $this->isHidden()
&& $option->isNegatable() === $this->isNegatable()
&& $option->isArray() === $this->isArray()
&& $option->isValueRequired() === $this->isValueRequired()
&& $option->isValueOptional() === $this->isValueOptional()
Expand Down
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.