Skip to content

Commit

Permalink
Fix referencing real $ENV vars when running dump-env
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolas-grekas committed Jun 5, 2019
1 parent bc7390d commit 443c86c
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 57 deletions.
93 changes: 36 additions & 57 deletions src/Command/DumpEnvCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Process\PhpProcess;
use Symfony\Component\Dotenv\Dotenv;
use Symfony\Flex\Options;

class DumpEnvCommand extends BaseCommand
Expand Down Expand Up @@ -71,65 +71,44 @@ private function loadEnv(string $path, string $env): array
throw new \RuntimeException(sprintf('Please run "composer install" before running this command: "%s" not found.', $autoloadFile));
}

$php = <<<'EOPHP'
<?php
use Symfony\Component\Dotenv\Dotenv;
require %s;
if (!class_exists(Dotenv::class)) {
exit;
}
foreach ($_SERVER as $k => $v) {
if (\is_string($v) && false !== getenv($k)) {
unset($_SERVER[$k]);
putenv($k);
}
}
$path = %s;
$env = %s;
$dotenv = new Dotenv();
$_ENV = ['APP_ENV' => $env];
if (method_exists($dotenv, 'loadEnv')) {
$dotenv->loadEnv($path);
} else {
// fallback code in case your Dotenv component is not 4.2 or higher (when loadEnv() was added)
$dotenv->load(file_exists($path) || !file_exists($p = "$path.dist") ? $path : $p);
if ('test' !== $env && file_exists($p = "$path.local")) {
$dotenv->load($p);
}
if (file_exists($p = "$path.$env")) {
$dotenv->load($p);
}
if (file_exists($p = "$path.$env.local")) {
$dotenv->load($p);
}
}
unset($_ENV['SYMFONY_DOTENV_VARS']);
echo serialize($_ENV);

EOPHP;

$php = sprintf($php, var_export($autoloadFile, true), var_export($path, true), var_export($env, true));
$process = new PhpProcess($php);
if (method_exists($process, 'inheritEnvironmentVariables')) {
$process->inheritEnvironmentVariables();
if (!class_exists(Dotenv::class)) {
throw new \RuntimeException('Please run "composer require symfony/dotenv" to load the ".env" files configuring the application.');
}
$process->mustRun();

if (!$env = $process->getOutput()) {
throw new \RuntimeException('Please run "composer require symfony/dotenv" to load the ".env" files configuring the application.');
$globalsBackup = [$_SERVER, $_ENV];
unset($_SERVER['APP_ENV']);
$_ENV = ['APP_ENV' => $env];
$_SERVER['SYMFONY_DOTENV_VARS'] = implode(',', array_keys($_SERVER));
putenv('SYMFONY_DOTENV_VARS='.$_SERVER['SYMFONY_DOTENV_VARS']);

try {
$dotenv = new Dotenv(false);

if (method_exists($dotenv, 'loadEnv')) {
$dotenv->loadEnv($path);
} else {
// fallback code in case your Dotenv component is not 4.2 or higher (when loadEnv() was added)
$dotenv->load(file_exists($path) || !file_exists($p = "$path.dist") ? $path : $p);

if ('test' !== $env && file_exists($p = "$path.local")) {
$dotenv->load($p);
}

if (file_exists($p = "$path.$env")) {
$dotenv->load($p);
}

if (file_exists($p = "$path.$env.local")) {
$dotenv->load($p);
}
}

unset($_ENV['SYMFONY_DOTENV_VARS']);
$env = $_ENV;
} finally {
list($_SERVER, $_ENV) = $globalsBackup;
}

return unserialize($env);
return $env;
}
}
38 changes: 38 additions & 0 deletions tests/Command/DumpEnvCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,44 @@ public function testEmptyOptionMustIgnoreContent()
unlink($envLocal);
}

/**
* @backupGlobals enabled
*/
public function testEnvCanBeReferenced()
{
@mkdir(FLEX_TEST_DIR);
$env = FLEX_TEST_DIR.'/.env';
$envLocal = FLEX_TEST_DIR.'/.env.local.php';
@unlink($env);
@unlink($envLocal);

$envContent = <<<'EOF'
BAR=$FOO
FOO=123
EOF;
file_put_contents($env, $envContent);

$_SERVER['FOO'] = 'Foo';
$_SERVER['BAR'] = 'Bar';

$command = $this->createCommandDumpEnv();
$command->execute([
'env' => 'prod',
]);

$this->assertFileExists($envLocal);

$vars = require $envLocal;
$this->assertSame([
'APP_ENV' => 'prod',
'BAR' => 'Foo',
'FOO' => '123',
], $vars);

unlink($env);
unlink($envLocal);
}

private function createCommandDumpEnv()
{
$command = new DumpEnvCommand(
Expand Down

0 comments on commit 443c86c

Please sign in to comment.