Skip to content

Fix reading config for symfony/runtime #867

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 17 additions & 15 deletions src/Command/DumpEnvCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

use Composer\Command\BaseCommand;
use Composer\Config;
use Composer\Factory;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
Expand Down Expand Up @@ -48,19 +47,22 @@ protected function configure()

protected function execute(InputInterface $input, OutputInterface $output): int
{
if ($env = $input->getArgument('env')) {
$_SERVER['APP_ENV'] = $env;
$runtime = $this->options->get('runtime') ?? [];
$envKey = $runtime['env_var_name'] ?? 'APP_ENV';

if ($env = $input->getArgument('env') ?? $runtime['env'] ?? null) {
$_SERVER[$envKey] = $env;
}

$path = $this->options->get('root-dir').'/.env';
$path = $this->options->get('root-dir').'/'.($runtime['dotenv_path'] ?? '.env');

if (!$env || !$input->getOption('empty')) {
$vars = $this->loadEnv($path, $env);
$env = $vars['APP_ENV'];
$vars = $this->loadEnv($path, $env, $runtime);
$env = $vars[$envKey];
}

if ($input->getOption('empty')) {
$vars = ['APP_ENV' => $env];
$vars = [$envKey => $env];
}

$vars = var_export($vars, true);
Expand All @@ -79,7 +81,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
return 0;
}

private function loadEnv(string $path, ?string $env): array
private function loadEnv(string $path, ?string $env, array $runtime): array
{
if (!file_exists($autoloadFile = $this->config->get('vendor-dir').'/autoload.php')) {
throw new \RuntimeException(sprintf('Please run "composer install" before running this command: "%s" not found.', $autoloadFile));
Expand All @@ -91,9 +93,10 @@ private function loadEnv(string $path, ?string $env): array
throw new \RuntimeException('Please run "composer require symfony/dotenv" to load the ".env" files configuring the application.');
}

$envKey = $runtime['env_var_name'] ?? 'APP_ENV';
$globalsBackup = [$_SERVER, $_ENV];
unset($_SERVER['APP_ENV']);
$_ENV = ['APP_ENV' => $env];
unset($_SERVER[$envKey]);
$_ENV = [$envKey => $env];
$_SERVER['SYMFONY_DOTENV_VARS'] = implode(',', array_keys($_SERVER));
putenv('SYMFONY_DOTENV_VARS='.$_SERVER['SYMFONY_DOTENV_VARS']);

Expand All @@ -105,18 +108,17 @@ private function loadEnv(string $path, ?string $env): array
}

if (!$env && file_exists($p = "$path.local")) {
$env = $_ENV['APP_ENV'] = $dotenv->parse(file_get_contents($p), $p)['APP_ENV'] ?? null;
$env = $_ENV[$envKey] = $dotenv->parse(file_get_contents($p), $p)[$envKey] ?? 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.');
throw new \RuntimeException(sprintf('Please provide the name of the environment either by passing it as command line argument or by defining the "%s" variable in the ".env.local" file.', $envKey));
}

$config = @json_decode(file_get_contents(Factory::getComposerFile()), true);
$testEnvs = $config['extra']['runtime']['test_envs'] ?? ['test'];
$testEnvs = $runtime['test_envs'] ?? ['test'];

if (method_exists($dotenv, 'loadEnv')) {
$dotenv->loadEnv($path, 'APP_ENV', 'dev', $testEnvs);
$dotenv->loadEnv($path, $envKey, 'dev', $testEnvs);
} 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);
Expand Down
19 changes: 13 additions & 6 deletions src/Command/InstallRecipesCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

use Composer\Command\BaseCommand;
use Composer\DependencyResolver\Operation\InstallOperation;
use Composer\Util\ProcessExecutor;
use Symfony\Component\Console\Exception\RuntimeException;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
Expand All @@ -26,11 +27,13 @@ class InstallRecipesCommand extends BaseCommand
/** @var Flex */
private $flex;
private $rootDir;
private $dotenvPath;

public function __construct(/* cannot be type-hinted */ $flex, string $rootDir)
public function __construct(/* cannot be type-hinted */ $flex, string $rootDir, string $dotenvPath = '.env')
{
$this->flex = $flex;
$this->rootDir = $rootDir;
$this->dotenvPath = $dotenvPath;

parent::__construct();
}
Expand Down Expand Up @@ -120,12 +123,15 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$operations[] = new InstallOperation($pkg);
}

if ($createEnvLocal = $force && file_exists($this->rootDir.'/.env') && file_exists($this->rootDir.'/.env.dist') && !file_exists($this->rootDir.'/.env.local')) {
rename($this->rootDir.'/.env', $this->rootDir.'/.env.local');
$dotenvFile = $this->dotenvPath;
$dotenvPath = $this->rootDir.'/'.$dotenvFile;

if ($createEnvLocal = $force && file_exists($dotenvPath) && file_exists($dotenvPath.'.dist') && !file_exists($dotenvPath.'.local')) {
rename($dotenvPath, $dotenvPath.'.local');
$pipes = [];
proc_close(proc_open(sprintf('git mv .env.dist .env > %s 2>&1 || %s .env.dist .env', $win ? 'NUL' : '/dev/null', $win ? 'rename' : 'mv'), $pipes, $pipes, $this->rootDir));
proc_close(proc_open(sprintf('git mv %s %s > %s 2>&1 || %s %1$s %2$s', ProcessExecutor::escape($dotenvFile.'.dist'), ProcessExecutor::escape($dotenvFile), $win ? 'NUL' : '/dev/null', $win ? 'rename' : 'mv'), $pipes, $pipes, $this->rootDir));
if (file_exists($this->rootDir.'/phpunit.xml.dist')) {
touch($this->rootDir.'/.env.test');
touch($dotenvPath.'.test');
}
}

Expand Down Expand Up @@ -156,8 +162,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$output[] = '';

if ($createEnvLocal) {
$root = '.' !== $this->rootDir ? $this->rootDir.'/' : '';
$output[] = ' To revert the changes made to .env files, run';
$output[] = sprintf(' <comment>git mv %s.env %1$s.env.dist</> && <comment>%s %1$s.env.local %1$s.env</>', '.' !== $this->rootDir ? $this->rootDir.'/' : '', $win ? 'rename' : 'mv');
$output[] = sprintf(' <comment>git mv %s %s</> && <comment>%s %s %1$s</>', ProcessExecutor::escape($root.$dotenvFile), ProcessExecutor::escape($root.$dotenvFile.'.dist'), $win ? 'rename' : 'mv', ProcessExecutor::escape($root.$dotenvFile.'.local'));
$output[] = '';
}

Expand Down
15 changes: 10 additions & 5 deletions src/Configurator/EnvConfigurator.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public function configure(Recipe $recipe, $vars, Lock $lock, array $options = []
$this->write('Adding environment variable defaults');

$this->configureEnvDist($recipe, $vars, $options['force'] ?? false);
if (!file_exists($this->options->get('root-dir').'/.env.test')) {
if (!file_exists($this->options->get('root-dir').'/'.($this->options->get('runtime')['dotenv_path'] ?? '.env').'.test')) {
$this->configurePhpUnit($recipe, $vars, $options['force'] ?? false);
}
}
Expand All @@ -49,7 +49,9 @@ public function update(RecipeUpdate $recipeUpdate, array $originalConfig, array

private function configureEnvDist(Recipe $recipe, $vars, bool $update)
{
foreach (['.env.dist', '.env'] as $file) {
$dotenvPath = $this->options->get('runtime')['dotenv_path'] ?? '.env';

foreach ([$dotenvPath.'.dist', $dotenvPath] as $file) {
$env = $this->options->get('root-dir').'/'.$file;
if (!is_file($env)) {
continue;
Expand Down Expand Up @@ -133,7 +135,9 @@ private function configurePhpUnit(Recipe $recipe, $vars, bool $update)

private function unconfigureEnvFiles(Recipe $recipe, $vars)
{
foreach (['.env', '.env.dist'] as $file) {
$dotenvPath = $this->options->get('runtime')['dotenv_path'] ?? '.env';

foreach ([$dotenvPath, $dotenvPath.'.dist'] as $file) {
$env = $this->options->get('root-dir').'/'.$file;
if (!file_exists($env)) {
continue;
Expand Down Expand Up @@ -200,7 +204,8 @@ private function generateRandomBytes($length = 16)

private function getContentsAfterApplyingRecipe(string $rootDir, Recipe $recipe, array $vars): array
{
$files = ['.env', '.env.dist', 'phpunit.xml.dist', 'phpunit.xml'];
$dotenvPath = $this->options->get('runtime')['dotenv_path'] ?? '.env';
$files = [$dotenvPath, $dotenvPath.'.dist', 'phpunit.xml.dist', 'phpunit.xml'];

if (0 === \count($vars)) {
return array_fill_keys($files, null);
Expand All @@ -217,7 +222,7 @@ private function getContentsAfterApplyingRecipe(string $rootDir, Recipe $recipe,
true
);

if (!file_exists($rootDir.'/.env.test')) {
if (!file_exists($rootDir.'/'.$dotenvPath.'.test')) {
$this->configurePhpUnit(
$recipe,
$vars,
Expand Down
6 changes: 4 additions & 2 deletions src/Configurator/MakefileConfigurator.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,13 @@ private function configureMakefile(Recipe $recipe, array $definitions, bool $upd
$data = "\n".ltrim($data, "\r\n");

if (!file_exists($makefile)) {
$envKey = $this->options->get('runtime')['env_var_name'] ?? 'APP_ENV';
$dotenvPath = $this->options->get('runtime')['dotenv_path'] ?? '.env';
file_put_contents(
$this->options->get('root-dir').'/Makefile',
<<<EOF
ifndef APP_ENV
include .env
ifndef {$envKey}
include {$dotenvPath}
endif

.DEFAULT_GOAL := help
Expand Down
9 changes: 6 additions & 3 deletions src/Flex.php
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ class_exists(__NAMESPACE__.str_replace('/', '\\', substr($file, \strlen(__DIR__)
$app->add(new Command\RemoveCommand($resolver));
$app->add(new Command\UnpackCommand($resolver));
$app->add(new Command\RecipesCommand($this, $this->lock, $rfs));
$app->add(new Command\InstallRecipesCommand($this, $this->options->get('root-dir')));
$app->add(new Command\InstallRecipesCommand($this, $this->options->get('root-dir'), $this->options->get('runtime')['dotenv_path'] ?? '.env'));
$app->add(new Command\UpdateRecipesCommand($this, $this->downloader, $rfs, $this->configurator, $this->options->get('root-dir')));
if (class_exists(Command\GenerateIdCommand::class)) {
$app->add(new Command\GenerateIdCommand(null));
Expand Down Expand Up @@ -391,9 +391,11 @@ public function update(Event $event, $operations = [])
public function install(Event $event)
{
$rootDir = $this->options->get('root-dir');
$runtime = $this->options->get('runtime');
$dotenvPath = $rootDir.'/'.($runtime['dotenv_path'] ?? '.env');

if (!file_exists("$rootDir/.env") && !file_exists("$rootDir/.env.local") && file_exists("$rootDir/.env.dist") && false === strpos(file_get_contents("$rootDir/.env.dist"), '.env.local')) {
copy($rootDir.'/.env.dist', $rootDir.'/.env');
if (!file_exists($dotenvPath) && !file_exists($dotenvPath.'.local') && file_exists($dotenvPath.'.dist') && false === strpos(file_get_contents($dotenvPath.'.dist'), '.env.local')) {
copy($dotenvPath.'.dist', $dotenvPath);
}

// Execute missing recipes
Expand Down Expand Up @@ -829,6 +831,7 @@ private function initOptions(): Options
'var-dir' => 'var',
'public-dir' => 'public',
'root-dir' => $extra['symfony']['root-dir'] ?? '.',
'runtime' => $extra['runtime'] ?? [],
], $extra);

return new Options($options, $this->io);
Expand Down
9 changes: 3 additions & 6 deletions tests/Command/DumpEnvCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,6 @@ public function testLoadLocalEnvWhenTestEnvIsNotEqual()
$env = FLEX_TEST_DIR.'/.env';
$envLocal = FLEX_TEST_DIR.'/.env.local';
$envLocalPhp = FLEX_TEST_DIR.'/.env.local.php';
$composer = FLEX_TEST_DIR.'/composer.json';

@unlink($envLocalPhp);

Expand All @@ -184,9 +183,8 @@ public function testLoadLocalEnvWhenTestEnvIsNotEqual()
APP_SECRET=abcdefgh123456789
EOF
);
file_put_contents(FLEX_TEST_DIR.'/composer.json', '{"extra":{"runtime":{"test_envs":[]}}}');

$command = $this->createCommandDumpEnv();
$command = $this->createCommandDumpEnv(['runtime' => ['test_envs' => []]]);
$command->execute([
'env' => 'test',
]);
Expand All @@ -202,14 +200,13 @@ public function testLoadLocalEnvWhenTestEnvIsNotEqual()
unlink($env);
unlink($envLocal);
unlink($envLocalPhp);
unlink($composer);
}

private function createCommandDumpEnv()
private function createCommandDumpEnv(array $options = [])
{
$command = new DumpEnvCommand(
new Config(false, __DIR__.'/../..'),
new Options(['root-dir' => FLEX_TEST_DIR])
new Options($options + ['root-dir' => FLEX_TEST_DIR])
);

$application = new Application();
Expand Down