diff --git a/CHANGELOG.md b/CHANGELOG.md index e004ed8..29fa368 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +5.4 +--- + + * Add `dotenv:dump` command to compile the contents of the .env files into a PHP-optimized file called `.env.local.php` + 5.1.0 ----- diff --git a/Command/DotenvDumpCommand.php b/Command/DotenvDumpCommand.php new file mode 100644 index 0000000..43456c8 --- /dev/null +++ b/Command/DotenvDumpCommand.php @@ -0,0 +1,128 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Dotenv\Command; + +use Symfony\Bundle\FrameworkBundle\Console\Application; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Dotenv\Dotenv; + +/** + * A console command to compile the contents of the .env files into a PHP-optimized file called .env.local.php. + * + * @internal + */ +final class DotenvDumpCommand extends Command +{ + protected static $defaultName = 'dotenv:dump'; + protected static $defaultDescription = 'Compiles .env files to .env.local.php'; + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setDescription('Compiles .env files to .env.local.php.') + ->setDefinition([ + new InputArgument('env', InputArgument::OPTIONAL, 'The application environment to dump .env files for - e.g. "prod".'), + ]) + ->addOption('empty', null, InputOption::VALUE_NONE, 'Ignore the content of .env files') + ->setHelp(<<<'EOT' +The %command.name% command compiles the contents of the .env files into a PHP-optimized file called .env.local.php. + + %command.full_name% +EOT + ) + ; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + /** @var Application $application */ + $application = $this->getApplication(); + $kernel = $application->getKernel(); + + if ($env = $input->getArgument('env')) { + $_SERVER['APP_ENV'] = $env; + } + + $path = $kernel->getProjectDir().'/.env'; + + if (!$env || !$input->getOption('empty')) { + $vars = $this->loadEnv($path, $env, $kernel->getProjectDir().'/composer.json'); + $env = $vars['APP_ENV']; + } + + if ($input->getOption('empty')) { + $vars = ['APP_ENV' => $env]; + } + + $vars = var_export($vars, true); + $vars = <<writeln('Successfully dumped .env files in .env.local.php'); + + return Command::SUCCESS; + } + + private function loadEnv(string $path, ?string $env, $composerFilePath): array + { + $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(); + + if (!$env && file_exists($p = "$path.local")) { + $env = $_ENV['APP_ENV'] = $dotenv->parse(file_get_contents($p), $p)['APP_ENV'] ?? null; + } + + if (!$env) { + throw new \RuntimeException('Please provide the name of the environment either by passing it as command line argument or by defining the "APP_ENV" variable in the ".env.local" file.'); + } + + $dotenv->loadEnv( + $path, + null, + 'dev', + json_decode(file_get_contents($composerFilePath), true)['extra']['runtime']['test_envs'] ?? ['test'] + ); + + if (isset($_ENV['SYMFONY_DOTENV_VARS'])) { + unset($_ENV['SYMFONY_DOTENV_VARS']); + } + $env = $_ENV; + } finally { + [$_SERVER, $_ENV] = $globalsBackup; + } + + return $env; + } +} diff --git a/composer.json b/composer.json index 9bd6cda..89de2c5 100644 --- a/composer.json +++ b/composer.json @@ -20,6 +20,8 @@ "symfony/deprecation-contracts": "^2.1" }, "require-dev": { + "symfony/console": "^5.4|^6.0", + "symfony/filesystem": "^4.4|^5.0|^6.0", "symfony/process": "^4.4|^5.0|^6.0" }, "autoload": {