Skip to content

Commit

Permalink
Add the Dotenv dumper and use it in the install tool and manager bundle
Browse files Browse the repository at this point in the history
  • Loading branch information
leofeyer committed Sep 19, 2019
1 parent 610ea53 commit 78299aa
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 74 deletions.
1 change: 1 addition & 0 deletions installation-bundle/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
},
"require-dev": {
"contao/manager-plugin": "^2.3.1",
"contao/test-case": "^3.0",
"php-http/guzzle6-adapter": "^1.1",
"phpunit/phpunit": "^7.5",
"symfony/phpunit-bridge": "^4.3"
Expand Down
97 changes: 97 additions & 0 deletions installation-bundle/src/Config/DotenvDumper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?php

declare(strict_types=1);

/*
* This file is part of Contao.
*
* (c) Leo Feyer
*
* @license LGPL-3.0-or-later
*/

namespace Contao\InstallationBundle\Config;

use Symfony\Component\Dotenv\Dotenv;
use Symfony\Component\Filesystem\Filesystem;

class DotenvDumper
{
/**
* @var string
*/
private $dotenvFile;

/**
* @var Filesystem
*/
private $filesystem;

/**
* @var array
*/
private $parameters = [];

public function __construct(string $dotenvFile, Filesystem $filesystem = null)
{
$this->dotenvFile = $dotenvFile;
$this->filesystem = $filesystem ?: new Filesystem();

if (!file_exists($dotenvFile)) {
return;
}

$parameters = (new Dotenv(false))->parse(file_get_contents($dotenvFile));

if (0 !== \count($parameters)) {
$this->parameters = array_merge($this->parameters, $parameters);
}
}

public function setParameter(string $name, $value): void
{
$this->parameters[$name] = $value;
}

public function setParameters(array $params): void
{
foreach ($params as $name => $value) {
$this->setParameter($name, $value);
}
}

public function unsetParameter(string $name): void
{
unset($this->parameters[$name]);
}

/**
* Dumps the parameters into the .env file.
*/
public function dump(): void
{
// Remove the .env file if there are no parameters
if (0 === \count($this->parameters)) {
$this->filesystem->remove($this->dotenvFile);

return;
}

$parameters = [];

foreach ($this->parameters as $key => $value) {
$parameters[] = $key.'='.$this->escape($value);
}

$this->filesystem->dumpFile($this->dotenvFile, implode("\n", $parameters)."\n");
}

private function escape($value)
{
if (\is_string($value)) {
return escapeshellarg($value);
}

return $value;
}
}
26 changes: 4 additions & 22 deletions installation-bundle/src/Controller/InstallationController.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
namespace Contao\InstallationBundle\Controller;

use Contao\Environment;
use Contao\InstallationBundle\Config\DotenvDumper;
use Contao\InstallationBundle\Database\AbstractVersionUpdate;
use Contao\InstallationBundle\Database\ConnectionFactory;
use Contao\InstallationBundle\Event\ContaoInstallationEvents;
Expand All @@ -21,7 +22,6 @@
use Patchwork\Utf8;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Finder\SplFileInfo;
use Symfony\Component\HttpFoundation\RedirectResponse;
Expand Down Expand Up @@ -324,26 +324,6 @@ private function setUpDatabaseConnection(): Response
*/
private function storeDatabaseUrl(array $parameters): void
{
$fs = new Filesystem();
$path = $this->getContainerParameter('kernel.project_dir').'/.env';
$content = '';

if ($fs->exists($path)) {
$lines = file($path, FILE_IGNORE_NEW_LINES);

if (false === $lines) {
throw new \RuntimeException(sprintf('Could not read "%s" file.', $path));
}

foreach ($lines as $line) {
if (0 === strpos($line, 'DATABASE_URL=')) {
continue;
}

$content .= $line."\n";
}
}

$url = sprintf(
'mysql://%s:%s@%s:%s/%s',
rawurlencode($parameters['parameters']['database_user']),
Expand All @@ -353,7 +333,9 @@ private function storeDatabaseUrl(array $parameters): void
rawurlencode($parameters['parameters']['database_name'])
);

$fs->dumpFile($path, $content."DATABASE_URL='".str_replace("'", "'\\''", $url)."'\n");
$dotenv = new DotenvDumper($this->getContainerParameter('kernel.project_dir').'/.env');
$dotenv->setParameter('DATABASE_URL', $url);
$dotenv->dump();
}

private function runDatabaseUpdates(): void
Expand Down
58 changes: 58 additions & 0 deletions installation-bundle/tests/Config/DotenvDumperTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

declare(strict_types=1);

/*
* This file is part of Contao.
*
* (c) Leo Feyer
*
* @license LGPL-3.0-or-later
*/

namespace Contao\InstallationBundle\Tests\Config;

use Contao\InstallationBundle\Config\DotenvDumper;
use Contao\TestCase\ContaoTestCase;

class DotenvDumperTest extends ContaoTestCase
{
public function testDumpsADotenvFile(): void
{
$dotenv = new DotenvDumper($this->getTempDir().'/.env');
$dotenv->setParameter('FOO1', 42);
$dotenv->setParameter('FOO2', '42');
$dotenv->setParameter('FOO3', 'String');
$dotenv->setParameter('FOO4', 'String with spaces');
$dotenv->setParameter('FOO5', '"DoubleQuotes"');
$dotenv->setParameter('FOO6', "'SingleQuotes'");
$dotenv->setParameter('FOO7', '$variable');
$dotenv->setParameter('FOO8', 'String with "double quotes" and \'single quotes\' and a $variable');
$dotenv->dump();

$expected = <<<'EOT'
FOO1=42
FOO2='42'
FOO3='String'
FOO4='String with spaces'
FOO5='"DoubleQuotes"'
FOO6=''\''SingleQuotes'\'''
FOO7='$variable'
FOO8='String with "double quotes" and '\''single quotes'\'' and a $variable'
EOT;

$this->assertSame($expected, file_get_contents($this->getTempDir().'/.env'));
}

public function testSupportsUnsettingParameters(): void
{
$dotenv = new DotenvDumper($this->getTempDir().'/.env.local');
$dotenv->setParameter('FOO', 'bar');
$dotenv->setParameter('BAR', 'foo');
$dotenv->unsetParameter('FOO');
$dotenv->dump();

$this->assertSame("BAR='foo'\n", file_get_contents($this->getTempDir().'/.env.local'));
}
}
6 changes: 5 additions & 1 deletion manager-bundle/bin/contao-api
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ set_time_limit(0);
@ini_set('display_errors', '1');
@ini_set('zlib.output_compression', '0');

$projectDir = \dirname(__DIR__, 4);
if (file_exists(__DIR__.'/../../../../autoload.php')) {
$projectDir = \dirname(__DIR__, 5);
} else {
$projectDir = \dirname(__DIR__, 4);
}

/** @var Composer\Autoload\ClassLoader $loader */
$loader = require $projectDir.'/vendor/autoload.php';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@

namespace Contao\ManagerBundle\ContaoManager\ApiCommand;

use Contao\InstallationBundle\Config\DotenvDumper;
use Contao\ManagerBundle\Api\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Filesystem\Filesystem;

class RemoveDotEnvCommand extends Command
{
Expand Down Expand Up @@ -52,34 +52,14 @@ protected function configure(): void
*/
protected function execute(InputInterface $input, OutputInterface $output): void
{
$fs = new Filesystem();
$path = $this->projectDir.'/.env';
$file = $this->projectDir.'/.env';

if (!$fs->exists($path)) {
if (!file_exists($file)) {
return;
}

$content = '';
$lines = file($path, FILE_IGNORE_NEW_LINES);

if (false === $lines) {
throw new \RuntimeException(sprintf('Could not read "%s" file.', $path));
}

$key = $input->getArgument('key');

foreach ($lines as $line) {
if (0 === strpos($line, $key.'=')) {
continue;
}

$content .= $line."\n";
}

if (empty($content)) {
$fs->remove($path);
} else {
$fs->dumpFile($path, $content);
}
$dotenv = new DotenvDumper($file);
$dotenv->unsetParameter($input->getArgument('key'));
$dotenv->dump();
}
}
29 changes: 4 additions & 25 deletions manager-bundle/src/ContaoManager/ApiCommand/SetDotEnvCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@

namespace Contao\ManagerBundle\ContaoManager\ApiCommand;

use Contao\InstallationBundle\Config\DotenvDumper;
use Contao\ManagerBundle\Api\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Filesystem\Filesystem;

class SetDotEnvCommand extends Command
{
Expand Down Expand Up @@ -53,29 +53,8 @@ protected function configure(): void
*/
protected function execute(InputInterface $input, OutputInterface $output): void
{
$fs = new Filesystem();
$path = $this->projectDir.'/.env';
$content = '';

$key = $input->getArgument('key');
$value = $input->getArgument('value');

if ($fs->exists($path)) {
$lines = file($path, FILE_IGNORE_NEW_LINES);

if (false === $lines) {
throw new \RuntimeException(sprintf('Could not read "%s" file.', $path));
}

foreach ($lines as $line) {
if (0 === strpos($line, $key.'=')) {
continue;
}

$content .= $line."\n";
}
}

$fs->dumpFile($path, $content.$key."='".str_replace("'", "'\\''", $value)."'\n");
$dotenv = new DotenvDumper($this->projectDir.'/.env');
$dotenv->setParameter($input->getArgument('key'), $input->getArgument('value'));
$dotenv->dump();
}
}

0 comments on commit 78299aa

Please sign in to comment.