Skip to content

Conversation

HMRDevil
Copy link
Contributor

Q A
Branch? 5.4
Bug fix? yes
New feature? no
Deprecations? no
Issues Fix #54640
License MIT

See #54640

Copy link
Member

@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

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

I had a look at the current code and it doesn't make much sense to me.
Your patch adds on top, but I'd propose rewriting the logic instead.

Here is the patch I ended up with (I worked on 7.1 so there might be some conflicts to resolve). Can you please borrow it and add a few test cases ideally? 🙏

DebugCommand.php
--- a/src/Symfony/Component/Dotenv/Command/DebugCommand.php
+++ b/src/Symfony/Component/Dotenv/Command/DebugCommand.php
@@ -15,6 +15,7 @@ use Symfony\Component\Console\Attribute\AsCommand;
 use Symfony\Component\Console\Command\Command;
 use Symfony\Component\Console\Completion\CompletionInput;
 use Symfony\Component\Console\Completion\CompletionSuggestions;
+use Symfony\Component\Console\Formatter\OutputFormatter;
 use Symfony\Component\Console\Input\InputArgument;
 use Symfony\Component\Console\Input\InputInterface;
 use Symfony\Component\Console\Output\OutputInterface;
@@ -69,7 +70,7 @@ EOT
         $filePath = $_SERVER['SYMFONY_DOTENV_PATH'] ?? $this->projectDirectory.\DIRECTORY_SEPARATOR.'.env';
 
         $envFiles = $this->getEnvFiles($filePath);
-        $availableFiles = array_filter($envFiles, fn (string $file) => is_file($file));
+        $availableFiles = array_filter($envFiles, 'is_file');
 
         if (\in_array(sprintf('%s.local.php', $filePath), $availableFiles, true)) {
             $io->warning(sprintf('Due to existing dump file (%s.local.php) all other dotenv files are skipped.', $this->getRelativeName($filePath)));
@@ -92,7 +93,7 @@ EOT
         if ($variables || null === $nameFilter) {
             $io->table(
                 array_merge(['Variable', 'Value'], array_map($this->getRelativeName(...), $availableFiles)),
-                $this->getVariables($availableFiles, $nameFilter)
+                $variables
             );
 
             $io->comment('Note that values might be different between web and CLI.');
@@ -112,43 +113,50 @@ EOT
 
     private function getVariables(array $envFiles, ?string $nameFilter): array
     {
-        $vars = $this->getAvailableVars();
-
-        $output = [];
+        $variables = [];
         $fileValues = [];
-        foreach ($vars as $var) {
+        $dotenvVars = array_flip(explode(',', $_SERVER['SYMFONY_DOTENV_VARS'] ?? ''));
+
+        foreach ($envFiles as $envFile) {
+            $fileValues[$envFile] = $this->loadValues($envFile);
+            $variables += $fileValues[$envFile];
+        }
+
+        foreach ($variables as $var => $varDetails) {
             if (null !== $nameFilter && 0 !== stripos($var, $nameFilter)) {
+                unset($variables[$var]);
                 continue;
             }
 
             $realValue = $_SERVER[$var];
-            $varDetails = [$var, $realValue];
-            foreach ($envFiles as $envFile) {
-                $values = $fileValues[$envFile] ??= $this->loadValues($envFile);
+            $varDetails = [$var, '<fg=green>'.OutputFormatter::escape($realValue).'</>'];
+            $varSeen = !isset($dotenvVars[$var]);
 
-                $varString = $values[$var] ?? '<fg=yellow>n/a</>';
-                $shortenedVar = $this->getHelper('formatter')->truncate($varString, 30);
-                $varDetails[] = $varString === $realValue ? '<fg=green>'.$shortenedVar.'</>' : $shortenedVar;
+            foreach ($envFiles as $envFile) {
+                if (null === $value = $fileValues[$envFile][$var] ?? null) {
+                    $varDetails[] = '<fg=yellow>n/a</>';
+                    continue;
+                }
+
+                $shortenedValue = OutputFormatter::escape($this->getHelper('formatter')->truncate($value, 30));
+                $varDetails[] = $value === $realValue && !$varSeen ? '<fg=green>'.$shortenedValue.'</>' : $shortenedValue;
+                $varSeen = $varSeen || $value === $realValue;
             }
 
-            $output[] = $varDetails;
+            $variables[$var] = $varDetails;
         }
 
-        return $output;
+        ksort($variables);
+
+        return $variables;
     }
 
     private function getAvailableVars(): array
     {
-        $dotenvVars = $_SERVER['SYMFONY_DOTENV_VARS'] ?? '';
-
-        if ('' === $dotenvVars) {
-            return [];
-        }
-
-        $vars = explode(',', $dotenvVars);
-        sort($vars);
+        $filePath = $_SERVER['SYMFONY_DOTENV_PATH'] ?? $this->projectDirectory.\DIRECTORY_SEPARATOR.'.env';
+        $envFiles = $this->getEnvFiles($filePath);
 
-        return $vars;
+        return array_keys($this->getVariables(array_filter($envFiles, 'is_file'), null));
     }
 
     private function getEnvFiles(string $filePath): array

Copy link
Member

@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

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

I back-ported the code from 7.1 after removing new features, this should minimize the diff and help with future merges, if any.
This is tested by fixing an existing test case that didn't expect the correct output.

@nicolas-grekas nicolas-grekas changed the title [Dotenv] show overridden vars too [Dotenv] show overridden vars too when running debug:dotenv Apr 29, 2024
@nicolas-grekas
Copy link
Member

Thank you @HMRDevil.

@nicolas-grekas nicolas-grekas merged commit b4f9da4 into symfony:5.4 Apr 29, 2024
@HMRDevil HMRDevil deleted the fix_54640 branch April 30, 2024 12:05
This was referenced Jun 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants