From a18cede9547646b3d8947608218e6d438ac992c9 Mon Sep 17 00:00:00 2001 From: Helmut Hummel Date: Tue, 1 Sep 2020 13:11:20 +0200 Subject: [PATCH] !!!Remove compat with older SF versions Also drop the possibility to configure a template file to be included with a cleaner way to expose env vars with different adapters. Raise PHP requirement to 7.2 --- .travis.yml | 2 -- README.md | 18 ++++++++-------- composer.json | 7 ++----- res/PHP/dotenv-include-sf-loadenv.php.tmpl | 6 ------ res/PHP/dotenv-include.php.tmpl | 5 ++--- src/Adapter/SymfonyDotEnv.php | 18 ++++++++++++++++ src/Adapter/SymfonyLoadEnv.php | 18 ++++++++++++++++ src/Config.php | 9 +++++--- src/DotEnvVars.php | 9 ++++++++ src/IncludeFile.php | 24 +++++++++++----------- tests/Unit/IncludeFileTest.php | 15 +++++++------- 11 files changed, 84 insertions(+), 47 deletions(-) delete mode 100644 res/PHP/dotenv-include-sf-loadenv.php.tmpl create mode 100644 src/Adapter/SymfonyDotEnv.php create mode 100644 src/Adapter/SymfonyLoadEnv.php create mode 100644 src/DotEnvVars.php diff --git a/.travis.yml b/.travis.yml index f2ca301..db03084 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,6 @@ language: php php: - - 7.0 - - 7.1 - 7.2 - 7.3 - 7.4 diff --git a/README.md b/README.md index 43b85c5..8f0c53b 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ You configure dotenv connector in the extra section of the root `composer.json` "extra": { "helhum/dotenv-connector": { "env-file": ".env", - "include-template-file": "{$vendor-dir}/helhum/dotenv-connector/res/PHP/dotenv-include.php.tmpl" + "adapter": "Helhum\\DotEnvConnector\\Adapter\\SymfonyDotEnv" } } ``` @@ -52,17 +52,17 @@ you have to be aware of that values with literal `$` signs need to be enclosed in single quotes. This may be the case if you use hashed values of credentials you pass via `.env`, for example. -#### `include-template-file` -You can specify a relative path from the base directory, -if you need a different template for the to be created include file. +#### `adapter` +You can specify a class that implements `\Helhum\DotEnvConnector\DotEnvVars` interface, +if you need a different way to expose env vars. + +*The default value* is "Helhum\DotEnvConnector\Adapter\SymfonyDotEnv", +which uses symfony/dotenv default parsing of the one .env file. -*The default value* is "{$vendor-dir}/helhum/dotenv-connector/res/PHP/dotenv-include.php.tmpl", which uses the -default template, which uses symfony/dotenv default parsing of the one .env file. -Change this option with great care and at your own risk. This could be useful though e.g. if you prefer to use another dotenv parsing library to expose the variables defined in .env or you want to switch to another parsing strategy of the Symfony dotenv parsing. In the latter case use -"{$vendor-dir}/helhum/dotenv-connector/res/PHP/dotenv-include-sf-loadenv.php.tmpl" as value for this option. -Have a look at the existing template files for examples for your own files in case you need them. +"Helhum\DotEnvConnector\Adapter\SymfonyLoadEnv" as value for this option. +Have a look at the existing implementations for examples. ## Feedback diff --git a/composer.json b/composer.json index df4140f..e01aecf 100644 --- a/composer.json +++ b/composer.json @@ -19,9 +19,9 @@ } }, "require": { - "php": "^7.0", + "php": "^7.2", "composer-plugin-api": "^1.0 || ^2.0", - "symfony/dotenv": "^3.3.0 || ^4.0 || ^5.0" + "symfony/dotenv": "^5.1" }, "require-dev": { "composer/composer": "^1.0 || 2.0.*@dev", @@ -29,9 +29,6 @@ "mikey179/vfsstream": "^1.6.0", "composer/semver": "^1.0 || 2.0.*@dev" }, - "conflict": { - "symfony/dotenv": ">=5.1.0" - }, "extra": { "class": "Helhum\\DotEnvConnector\\Plugin", "branch-alias": { diff --git a/res/PHP/dotenv-include-sf-loadenv.php.tmpl b/res/PHP/dotenv-include-sf-loadenv.php.tmpl deleted file mode 100644 index 0e89202..0000000 --- a/res/PHP/dotenv-include-sf-loadenv.php.tmpl +++ /dev/null @@ -1,6 +0,0 @@ -loadEnv($dotEnvFile); - } -}, '{$env-file}'); diff --git a/res/PHP/dotenv-include.php.tmpl b/res/PHP/dotenv-include.php.tmpl index 88834cb..ddf7ce0 100644 --- a/res/PHP/dotenv-include.php.tmpl +++ b/res/PHP/dotenv-include.php.tmpl @@ -1,6 +1,5 @@ load($dotEnvFile); - } + $class = '{$adapter}'; + (new $class())->exposeToEnvironment($dotEnvFile); }, '{$env-file}'); diff --git a/src/Adapter/SymfonyDotEnv.php b/src/Adapter/SymfonyDotEnv.php new file mode 100644 index 0000000..b8911f6 --- /dev/null +++ b/src/Adapter/SymfonyDotEnv.php @@ -0,0 +1,18 @@ +usePutenv(); + $dotEnv->load($dotEnvFile); + } + } +} diff --git a/src/Adapter/SymfonyLoadEnv.php b/src/Adapter/SymfonyLoadEnv.php new file mode 100644 index 0000000..92a430f --- /dev/null +++ b/src/Adapter/SymfonyLoadEnv.php @@ -0,0 +1,18 @@ +usePutenv(); + $dotEnv->loadEnv($dotEnvFile); + } + } +} diff --git a/src/Config.php b/src/Config.php index 5bb7f65..3c94fdb 100644 --- a/src/Config.php +++ b/src/Config.php @@ -10,16 +10,18 @@ * file that was distributed with this source code. */ +use Helhum\DotEnvConnector\Adapter\SymfonyDotEnv; + class Config { - const RELATIVE_PATHS = 1; + private const RELATIVE_PATHS = 1; /** * @var array */ public static $defaultConfig = [ 'env-file' => '.env', - 'include-template-file' => '{$vendor-dir}/helhum/dotenv-connector/res/PHP/dotenv-include.php.tmpl', + 'adapter' => SymfonyDotEnv::class, ]; /** @@ -71,8 +73,9 @@ public function get($key, $flags = 0) return null; } switch ($key) { + case 'adapter': + return $this->config[$key]; case 'env-file': - case 'include-template-file': $val = rtrim($this->process($this->config[$key], $flags), '/\\'); return ($flags & self::RELATIVE_PATHS === 1) ? $val : $this->realpath($val); default: diff --git a/src/DotEnvVars.php b/src/DotEnvVars.php new file mode 100644 index 0000000..a9413bb --- /dev/null +++ b/src/DotEnvVars.php @@ -0,0 +1,9 @@ +config = $config; $this->loader = $loader; $this->includeFile = $includeFile; - $this->includeFileTemplate = $includeFileTemplate ?: $config->get('include-template-file'); + $this->includeFileTemplate = $includeFileTemplate ?? self::defaultTemplate; $this->filesystem = $filesystem ?: new Filesystem(); } public function dump(): bool { + $this->loader->register(); $this->filesystem->ensureDirectoryExists(dirname($this->includeFile)); $successfullyWritten = false !== @file_put_contents($this->includeFile, $this->getIncludeFileContent()); if ($successfullyWritten) { // Expose env vars of a possibly available .env file for following composer plugins - $this->loader->register(); require $this->includeFile; - $this->loader->unregister(); } + $this->loader->unregister(); return $successfullyWritten; } @@ -75,21 +78,18 @@ public function dump(): bool */ private function getIncludeFileContent(): string { - if (!file_exists($this->includeFileTemplate)) { - if (!empty($this->includeFileTemplate)) { - throw new \RuntimeException('Include file template defined for helhum/dotenv-connector does not exist!', 1581515568); - } - // We get here when include file template is empty, which could be a misconfiguration, but more likely happens - // during plugin package upgrades. In this case we provide the default value for smoother upgrades. - $this->includeFileTemplate = __DIR__ . '/../res/PHP/dotenv-include.php.tmpl'; - } $envFile = $this->config->get('env-file'); + $adapterClass = $this->config->get('adapter') ?: SymfonyDotEnv::class; + if (!in_array(DotEnvVars::class ,class_implements($adapterClass), true)) { + throw new \RuntimeException(sprintf('Adapter "%s" does not implement DotEnvVars interface', $adapterClass), 1598957197); + } $pathToEnvFileCode = $this->filesystem->findShortestPathCode( $this->includeFile, $envFile ); $includeFileContent = file_get_contents($this->includeFileTemplate); $includeFileContent = $this->replaceToken('env-file', $pathToEnvFileCode, $includeFileContent); + $includeFileContent = $this->replaceToken('adapter', '\\' . $adapterClass . '::class', $includeFileContent); return $includeFileContent; } diff --git a/tests/Unit/IncludeFileTest.php b/tests/Unit/IncludeFileTest.php index 397f179..edb1d8c 100644 --- a/tests/Unit/IncludeFileTest.php +++ b/tests/Unit/IncludeFileTest.php @@ -2,6 +2,7 @@ namespace Helhum\DotEnvConnector\Tests\Unit; use Composer\Autoload\ClassLoader; +use Helhum\DotEnvConnector\Adapter\SymfonyDotEnv; use Helhum\DotEnvConnector\Config; use Helhum\DotEnvConnector\IncludeFile; @@ -29,7 +30,7 @@ public function dumpDumpsFile() { $configProphecy = $this->prophesize(Config::class); $configProphecy->get('env-file')->willReturn(__DIR__ . '/Fixtures/env/.env'); - $configProphecy->get('include-template-file')->willReturn(__DIR__ . '/../../res/PHP/dotenv-include.php.tmpl'); + $configProphecy->get('adapter')->willReturn(SymfonyDotEnv::class); $loaderProphecy = $this->prophesize(ClassLoader::class); $loaderProphecy->register()->shouldBeCalled(); $loaderProphecy->unregister()->shouldBeCalled(); @@ -47,7 +48,7 @@ public function includingFileExposesEnvVars() { $configProphecy = $this->prophesize(Config::class); $configProphecy->get('env-file')->willReturn(__DIR__ . '/Fixtures/env/.env'); - $configProphecy->get('include-template-file')->willReturn(__DIR__ . '/../../res/PHP/dotenv-include.php.tmpl'); + $configProphecy->get('adapter')->willReturn(SymfonyDotEnv::class); $loaderProphecy = $this->prophesize(ClassLoader::class); $loaderProphecy->register()->shouldBeCalled(); $loaderProphecy->unregister()->shouldBeCalled(); @@ -68,7 +69,7 @@ public function includingFileDoesNothingIfEnvVarSet() putenv('APP_ENV=1'); $configProphecy = $this->prophesize(Config::class); $configProphecy->get('env-file')->willReturn(__DIR__ . '/Fixtures/env/.env'); - $configProphecy->get('include-template-file')->willReturn(__DIR__ . '/../../res/PHP/dotenv-include.php.tmpl'); + $configProphecy->get('adapter')->willReturn(SymfonyDotEnv::class); $loaderProphecy = $this->prophesize(ClassLoader::class); $loaderProphecy->register()->shouldBeCalled(); $loaderProphecy->unregister()->shouldBeCalled(); @@ -88,7 +89,7 @@ public function includingFileDoesNothingIfEnvFileDoesNotExist() { $configProphecy = $this->prophesize(Config::class); $configProphecy->get('env-file')->willReturn(__DIR__ . '/Fixtures/env/.no-env'); - $configProphecy->get('include-template-file')->willReturn(__DIR__ . '/../../res/PHP/dotenv-include.php.tmpl'); + $configProphecy->get('adapter')->willReturn(SymfonyDotEnv::class); $loaderProphecy = $this->prophesize(ClassLoader::class); $loaderProphecy->register()->shouldBeCalled(); $loaderProphecy->unregister()->shouldBeCalled(); @@ -108,10 +109,10 @@ public function dumpReturnsFalseIfFileCannotBeWritten() { $configProphecy = $this->prophesize(Config::class); $configProphecy->get('env-file')->willReturn(__DIR__ . '/Fixtures/env/.no-env'); - $configProphecy->get('include-template-file')->willReturn(__DIR__ . '/../../res/PHP/dotenv-include.php.tmpl'); + $configProphecy->get('adapter')->willReturn(SymfonyDotEnv::class); $loaderProphecy = $this->prophesize(ClassLoader::class); - $loaderProphecy->register()->shouldNotBeCalled(); - $loaderProphecy->unregister()->shouldNotBeCalled(); + $loaderProphecy->register()->shouldBeCalled(); + $loaderProphecy->unregister()->shouldBeCalled(); mkdir(__DIR__ . '/Fixtures/foo', 000); $includeFilePath = __DIR__ . '/Fixtures/foo/include.php';