8000 feature #46502 [Dotenv] Variable filter added to debug command (rmika… · symfony/symfony@ca4615a · GitHub
[go: up one dir, main page]

Skip to content

Commit ca4615a

Browse files
committed
feature #46502 [Dotenv] Variable filter added to debug command (rmikalkenas)
This PR was merged into the 6.2 branch. Discussion ---------- [Dotenv] Variable filter added to debug command | Q | A | ------------- | --- | Branch? | 6.2 | Bug fix? | no | New feature? | yes | Deprecations? | no | Tickets | - | License | MIT | Doc PR | Will prepare on implementation approval For applications that use many environment variables there is no way to efficiently filter a single variable. Of course there is always a `grep` command, but with it you are loosing part of the information that symfony debug command provides. Added a new `name` argument to the command, to be able to filter debug output by variable's name Commits ------- a754669 [Dotenv] Variable filter added to debug command
2 parents c5aeafe + a754669 commit ca4615a

File tree

3 files changed

+136
-10
lines changed

3 files changed

+136
-10
lines changed

src/Symfony/Component/Dotenv/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
6.2
5+
---
6+
7+
* Add new `filter` argument to `debug:dotenv` command to be able to filter certain variable
8+
49
5.4
510
---
611

src/Symfony/Component/Dotenv/Command/DebugCommand.php

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\Component\Console\Attribute\AsCommand;
1515
use Symfony\Component\Console\Command\Command;
16+
use Symfony\Component\Console\Input\InputArgument;
1617
use Symfony\Component\Console\Input\InputInterface;
1718
use Symfony\Component\Console\Output\OutputInterface;
1819
use Symfony\Component\Console\Style\SymfonyStyle;
@@ -47,6 +48,25 @@ public function __construct(string $kernelEnvironment, string $projectDirectory)
4748
parent::__construct();
4849
}
4950

51+
protected function configure(): void
52+
{
53+
$this
54+
->setDefinition([
55+
new InputArgument('filter', InputArgument::OPTIONAL, 'The name of an environment variable or a filter.', null, $this->getAvailableVars(...)),
56+
])
57+
->setHelp(<<<'EOT'
58+
The <info>%command.full_name%</info> command displays all the environment variables configured by dotenv:
59+
60+
<info>php %command.full_name%</info>
61+
62+
To get specific variable, specify its full or partial name:
63+
64+
<info>php %command.full_name% FOO_BAR</info>
65+
66+
EOT
67+
);
68+
}
69+
5070
protected function execute(InputInterface $input, OutputInterface $output): int
5171
{
5272
$io = new SymfonyStyle($input, $output);
@@ -78,25 +98,36 @@ protected function execute(InputInterface $input, OutputInterface $output): int
7898
: sprintf('<fg=red>⨯</> %s', $envFile);
7999
}, $envFiles));
80100

101+
$nameFilter = $input->getArgument('filter');
102+
$variables = $this->getVariables($availableFiles, $nameFilter);
103+
81104
$io->section('Variables');
82-
$io->table(
83-
array_merge(['Variable', 'Value'], $availableFiles),
84-
$this->getVariables($availableFiles)
85-
);
86105

87-
$io->comment('Note real values might be different between web and CLI.');
106+
if ($variables || null === $nameFilter) {
107+
$io->table(
108+
array_merge(['Variable', 'Value'], $availableFiles),
109+
$this->getVariables($availableFiles, $nameFilter)
110+
);
111+
112+
$io->comment('Note that values might be different between web and CLI.');
113+
} else {
114+
$io->warning(sprintf('No variables match the given filter "%s".', $nameFilter));
115+
}
88116

89117
return 0;
90118
}
91119

92-
private function getVariables(array $envFiles): array
120+
private function getVariables(array $envFiles, ?string $nameFilter): array
93121
{
94-
$vars = explode(',', $_SERVER['SYMFONY_DOTENV_VARS'] ?? '');
95-
sort($vars);
122+
$vars = $this->getAvailableVars();
96123

97124
$output = [];
98125
$fileValues = [];
99126
foreach ($vars as $var) {
127+
if (null !== $nameFilter && 0 !== stripos($var, $nameFilter)) {
128+
continue;
129+
}
130+
100131
$realValue = $_SERVER[$var];
101132
$varDetails = [$var, $realValue];
102133
foreach ($envFiles as $envFile) {
@@ -113,6 +144,14 @@ private function getVariables(array $envFiles): array
113144
return $output;
114145
}
115146

147+
private function getAvailableVars(): array
148+
{
149+
$vars = explode(',', $_SERVER['SYMFONY_DOTENV_VARS'] ?? '');
150+
sort($vars);
151+
152+
return $vars;
153+
}
154+
116155
private function getEnvFiles(): array
117156
{
118157
$files = [

src/Symfony/Component/Dotenv/Tests/Command/DebugCommandTest.php

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\Console\Helper\FormatterHelper;
1616
use Symfony\Component\Console\Helper\HelperSet;
17+
use Symfony\Component\Console\Tester\CommandCompletionTester;
1718
use Symfony\Component\Console\Tester\CommandTester;
1819
use Symfony\Component\Dotenv\Command\DebugCommand;
1920
use Symfony\Component\Dotenv\Dotenv;
@@ -138,15 +139,96 @@ public function testWarningOnPhpEnvFile()
138139
$this->assertStringContainsString('[WARNING] Due to existing dump file (.env.local.php)', $output);
139140
}
140141

141-
private function executeCommand(string $projectDirectory, string $env): string
142+
public function testScenario1InDevEnvWithNameFilter()
143+
{
144+
$output = $this->executeCommand(__DIR__.'/Fixtures/Scenario1', 'dev', ['filter' => 'FoO']);
145+
146+
// Scanned Files
147+
$this->assertStringContainsString('⨯ .env.local.php', $output);
148+
$this->assertStringContainsString('⨯ .env.dev.local', $output);
149+
$this->assertStringContainsString('⨯ .env.dev', $output);
150+
$this->assertStringContainsString('✓ .env.local', $output);
151+
$this->assertStringContainsString('✓ .env'.\PHP_EOL, $output);
152+
153+
// Skipped Files
154+
$this->assertStringNotContainsString('.env.prod', $output);
155+
$this->assertStringNotContainsString('.env.test', $output);
156+
$this->assertStringNotContainsString('.env.dist', $output);
157+
158+
// Variables
159+
$this->assertStringContainsString('Variable Value .env.local .env', $output);
160+
$this->assertStringContainsString('FOO baz baz bar', $output);
161+
$this->assertStringNotContainsString('TEST123 true n/a true', $output);
162+
}
163+
164+
public function testScenario1InProdEnvWithMissingNameFilter()
165+
{
166+
$output = $this->executeCommand(__DIR__.'/Fixtures/Scenario1', 'prod', ['filter' => 'unknown']);
167+
168+
// Scanned Files
169+
$this->assertStringContainsString('⨯ .env.local.php', $output);
170+
$this->assertStringContainsString('✓ .env.prod.local', $output);
171+
$this->assertStringContainsString('⨯ .env.prod', $output);
172+
$this->assertStringContainsString('✓ .env.local', $output);
173+
$this->assertStringContainsString('✓ .env'.\PHP_EOL, $output);
174+
175+
// Skipped Files
176+
$this->assertStringNotContainsString('.env.dev', $output);
177+
$this->assertStringNotContainsString('.env.test', $output);
178+
$this->assertStringNotContainsString('.env.dist', $output);
179+
180+
// Variables
181+
$this->assertStringContainsString('[WARNING] No variables match the given filter "unknown".', $output);
182+
$this->assertStringNotContainsString('Variable Value .env.prod.local .env.local .env', $output);
183+
$this->assertStringNotContainsString('FOO baz n/a baz bar', $output);
184+
$this->assertStringNotContainsString('HELLO world world n/a n/a', $output);
185+
$this->assertStringNotContainsString('TEST123 true n/a n/a true', $output);
186+
}
187+
188+
public function testScenario2InProdEnvWithNameFilterPrefix()
189+
{
190+
$output = $this->executeCommand(__DIR__.'/Fixtures/Scenario2', 'prod', ['filter' => 'tes']);
191+
192+
// Scanned Files
193+
$this->assertStringContainsString('✓ .env.local.php', $output);
194+
$this->assertStringContainsString('⨯ .env.prod.local', $output);
195+
$this->assertStringContainsString('✓ .env.prod', $output);
196+
$this->assertStringContainsString('⨯ .env.local', $output);
197+
$this->assertStringContainsString('✓ .env.dist', $output);
198+
199+
// Skipped Files
200+
$this->assertStringNotContainsString('.env'.\PHP_EOL, $output);
201+
$this->assertStringNotContainsString('.env.dev', $output);
202+
$this->assertStringNotContainsString('.env.test', $output);
203+
204+
// Variables
205+
$this->assertStringContainsString('Variable Value .env.local.php .env.prod .env.dist', $output);
206+
$this->assertStringNotContainsString('FOO BaR BaR BaR n/a', $output);
207+
$this->assertStringContainsString('TEST 1234 1234 1234 0000', $output);
208+
}
209+
210+
public function testCompletion()
211+
{
212+
$env = 'prod';
213+
$projectDirectory = __DIR__.'/Fixtures/Scenario2';
214+
215+
$_SERVER['TEST_ENV_KEY'] = $env;
216+
(new Dotenv('TEST_ENV_KEY'))->bootEnv($projectDirectory.'/.env');
217+
218+
$command = new DebugCommand($env, $projectDirectory);
219+
$tester = new CommandCompletionTester($command);
220+
$this->assertSame(['FOO', 'HELLO', 'TEST', 'TEST123'], $tester->complete(['']));
221+
}
222+
223+
private function executeCommand(string $projectDirectory, string $env, array $input = []): string
142224
{
143225
$_SERVER['TEST_ENV_KEY'] = $env;
144226
(new Dotenv('TEST_ENV_KEY'))->bootEnv($projectDirectory.'/.env');
145227

146228
$command = new DebugCommand($env, $projectDirectory);
147229
$command->setHelperSet(new HelperSet([new FormatterHelper()]));
148230
$tester = new CommandTester($command);
149-
$tester->execute([]);
231+
$tester->execute($input);
150232

151233
return $tester->getDisplay();
152234
}

0 commit comments

Comments
 (0)
0