From 390eb7ed7e36b6f35555ad805aec6211c0f086d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Tue, 22 Jun 2021 19:22:15 +0200 Subject: [PATCH] Allow dupplicate negative option --- .../Console/Input/InputDefinition.php | 4 +-- .../Component/Console/Input/InputOption.php | 29 +++++++++++++++++-- .../Tests/Input/InputDefinitionTest.php | 10 +++---- .../Console/Tests/Input/InputOptionTest.php | 13 +++++++++ 4 files changed, 45 insertions(+), 11 deletions(-) diff --git a/src/Symfony/Component/Console/Input/InputDefinition.php b/src/Symfony/Component/Console/Input/InputDefinition.php index fcbfd5271b174..4b3854679c673 100644 --- a/src/Symfony/Component/Console/Input/InputDefinition.php +++ b/src/Symfony/Component/Console/Input/InputDefinition.php @@ -231,7 +231,7 @@ 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()])) { + if (isset($this->negations[$option->getName()]) && !$option->equals($this->options[$this->negations[$option->getName()]])) { throw new LogicException(sprintf('An option named "%s" already exists.', $option->getName())); } @@ -252,7 +252,7 @@ public function addOption(InputOption $option) if ($option->isNegatable()) { $negatedName = 'no-'.$option->getName(); - if (isset($this->options[$negatedName])) { + if (isset($this->options[$negatedName]) && !$option->equals($this->options[$negatedName])) { throw new LogicException(sprintf('An option named "%s" already exists.', $negatedName)); } $this->negations[$negatedName] = $option->getName(); diff --git a/src/Symfony/Component/Console/Input/InputOption.php b/src/Symfony/Component/Console/Input/InputOption.php index 612b6d6d7cb07..e9249dc402b41 100644 --- a/src/Symfony/Component/Console/Input/InputOption.php +++ b/src/Symfony/Component/Console/Input/InputOption.php @@ -219,13 +219,36 @@ public function getDescription() */ public function equals(self $option) { - return $option->getName() === $this->getName() + if ($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() - ; + ) { + return true; + } + + if (!($option->isNegatable() xor $this->isNegatable())) { + return false; + } + + if ($option->isNegatable()) { + $n = $option; + $p = $this; + } else { + $p = $option; + $n = $this; + } + + return ( + ( + $n->getName() === $p->getName() + && $n->getShortcut() === $p->getShortcut() + ) || ( + 'no-'.$n->getName() === $p->getName() + && null === $p->getShortcut() + ) + ) && !$p->acceptValue(); } } diff --git a/src/Symfony/Component/Console/Tests/Input/InputDefinitionTest.php b/src/Symfony/Component/Console/Tests/Input/InputDefinitionTest.php index 11c6ae165eb7c..0c33bbe284644 100644 --- a/src/Symfony/Component/Console/Tests/Input/InputDefinitionTest.php +++ b/src/Symfony/Component/Console/Tests/Input/InputDefinitionTest.php @@ -244,22 +244,20 @@ public function testAddDuplicateOption() public function testAddDuplicateNegatedOption() { - $this->expectException(\LogicException::class); - $this->expectExceptionMessage('An option named "no-foo" already exists.'); - $definition = new InputDefinition(); $definition->addOption(new InputOption('no-foo')); $definition->addOption(new InputOption('foo', null, InputOption::VALUE_NEGATABLE)); + + $this->expectNotToPerformAssertions(); } public function testAddDuplicateNegatedReverseOption() { - $this->expectException(\LogicException::class); - $this->expectExceptionMessage('An option named "no-foo" already exists.'); - $definition = new InputDefinition(); $definition->addOption(new InputOption('foo', null, InputOption::VALUE_NEGATABLE)); $definition->addOption(new InputOption('no-foo')); + + $this->expectNotToPerformAssertions(); } public function testAddDuplicateShortcutOption() diff --git a/src/Symfony/Component/Console/Tests/Input/InputOptionTest.php b/src/Symfony/Component/Console/Tests/Input/InputOptionTest.php index 8ab83d036fe05..4b5d91d4c65bc 100644 --- a/src/Symfony/Component/Console/Tests/Input/InputOptionTest.php +++ b/src/Symfony/Component/Console/Tests/Input/InputOptionTest.php @@ -193,5 +193,18 @@ public function testEquals() $option = new InputOption('foo', 'f', null, 'Some description'); $option2 = new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL, 'Some description'); $this->assertFalse($option->equals($option2)); + + $option = new InputOption('foo', null, InputOption::VALUE_NEGATABLE, 'Some description'); + $option2 = new InputOption('no-foo', null, null, 'Alternative description'); + $this->assertTrue($option->equals($option2)); + $this->assertTrue($option2->equals($option)); + + $option = new InputOption('foo', null, InputOption::VALUE_NEGATABLE, 'Some description'); + $option2 = new InputOption('foo', null, null, 'Alternative description'); + $this->assertTrue($option->equals($option2)); + + $option = new InputOption('foo', null, InputOption::VALUE_NEGATABLE, 'Some description'); + $option2 = new InputOption('bar', null, null, 'Alternative description'); + $this->assertFalse($option->equals($option2)); } }