Skip to content

Commit bd07a24

Browse files
authored
Merge pull request #87 from stecman/conflicting-options
Prevent global/application options conflicting with CompletionCommand
2 parents 4d1901e + 08a5263 commit bd07a24

File tree

2 files changed

+87
-1
lines changed

2 files changed

+87
-1
lines changed

src/CompletionCommand.php

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
class CompletionCommand extends SymfonyCommand
1212
{
13-
1413
/**
1514
* @var CompletionHandler
1615
*/
@@ -49,6 +48,52 @@ public function getNativeDefinition()
4948
return $this->createDefinition();
5049
}
5150

51+
/**
52+
* Ignore user-defined global options
53+
*
54+
* Any global options defined by user-code are meaningless to this command.
55+
* Options outside of the core defaults are ignored to avoid name and shortcut conflicts.
56+
*/
57+
public function mergeApplicationDefinition($mergeArgs = true)
58+
{
59+
// Get current application options
60+
$appDefinition = $this->getApplication()->getDefinition();
61+
$originalOptions = $appDefinition->getOptions();
62+
63+
// Temporarily replace application options with a filtered list
64+
$appDefinition->setOptions(
65+
$this->filterApplicationOptions($originalOptions)
66+
);
67+
68+
parent::mergeApplicationDefinition($mergeArgs);
69+
70+
// Restore original application options
71+
$appDefinition->setOptions($originalOptions);
72+
}
73+
74+
/**
75+
* Reduce the passed list of options to the core defaults (if they exist)
76+
*
77+
* @param InputOption[] $appOptions
78+
* @return InputOption[]
79+
*/
80+
protected function filterApplicationOptions(array $appOptions)
81+
{
82+
return array_filter($appOptions, function(InputOption $option) {
83+
static $coreOptions = array(
84+
'help' => true,
85+
'quiet' => true,
86+
'verbose' => true,
87+
'version' => true,
88+
'ansi' => true,
89+
'no-ansi' => true,
90+
'no-interaction' => true,
91+
);
92+
93+
return isset($coreOptions[$option->getName()]);
94+
});
95+
}
96+
5297
protected function execute(InputInterface $input, OutputInterface $output)
5398
{
5499
$this->handler = new CompletionHandler($this->getApplication());
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
namespace Stecman\Component\Symfony\Console\BashCompletion\Tests;
4+
5+
use PHPUnit\Framework\TestCase;
6+
use Stecman\Component\Symfony\Console\BashCompletion\CompletionCommand;
7+
use Symfony\Component\Console\Application;
8+
use Symfony\Component\Console\Input\InputOption;
9+
use Symfony\Component\Console\Input\StringInput;
10+
use Symfony\Component\Console\Output\NullOutput;
11+
12+
class CompletionCommandTest extends TestCase
13+
{
14+
/**
15+
* Ensure conflicting options names and shortcuts from the application do not break the completion command
16+
*/
17+
public function testConflictingGlobalOptions()
18+
{
19+
$app = new Application('Base application');
20+
21+
// Conflicting option shortcut
22+
$app->getDefinition()->addOption(
23+
new InputOption('conflicting-shortcut', 'g', InputOption::VALUE_NONE)
24+
);
25+
26+
// Conflicting option name
27+
$app->getDefinition()->addOption(
28+
new InputOption('program', null, InputOption::VALUE_REQUIRED)
29+
);
30+
31+
$app->add(new CompletionCommand());
32+
33+
// Check completion command doesn't throw
34+
$app->doRun(new StringInput('_completion -g --program foo'), new NullOutput());
35+
$app->doRun(new StringInput('_completion --help'), new NullOutput());
36+
$app->doRun(new StringInput('help _completion'), new NullOutput());
37+
38+
// Check default options are available
39+
$app->doRun(new StringInput('_completion -V -vv --no-ansi --quiet'), new NullOutput());
40+
}
41+
}

0 commit comments

Comments
 (0)