Skip to content

Commit

Permalink
!!!Remove compat with older SF versions
Browse files Browse the repository at this point in the history
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
  • Loading branch information
helhum committed Sep 1, 2020
1 parent 9ce9bb6 commit a18cede
Show file tree
Hide file tree
Showing 11 changed files with 84 additions and 47 deletions.
2 changes: 0 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
language: php

php:
- 7.0
- 7.1
- 7.2
- 7.3
- 7.4
Expand Down
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
```
Expand All @@ -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

Expand Down
7 changes: 2 additions & 5 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,16 @@
}
},
"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",
"phpunit/phpunit": "^5",
"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": {
Expand Down
6 changes: 0 additions & 6 deletions res/PHP/dotenv-include-sf-loadenv.php.tmpl

This file was deleted.

5 changes: 2 additions & 3 deletions res/PHP/dotenv-include.php.tmpl
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<?php
call_user_func(static function($dotEnvFile) {
if (!getenv('APP_ENV') && file_exists($dotEnvFile)) {
(new \Symfony\Component\Dotenv\Dotenv(true))->load($dotEnvFile);
}
$class = '{$adapter}';
(new $class())->exposeToEnvironment($dotEnvFile);
}, '{$env-file}');
18 changes: 18 additions & 0 deletions src/Adapter/SymfonyDotEnv.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
namespace Helhum\DotEnvConnector\Adapter;

use Helhum\DotEnvConnector\DotEnvVars;
use Symfony\Component\Dotenv\Dotenv;

class SymfonyDotEnv implements DotEnvVars
{
public function exposeToEnvironment(string $dotEnvFile): void
{
if (!getenv('APP_ENV') && file_exists($dotEnvFile)) {
$dotEnv = new Dotenv();
$dotEnv->usePutenv();
$dotEnv->load($dotEnvFile);
}
}
}
18 changes: 18 additions & 0 deletions src/Adapter/SymfonyLoadEnv.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
namespace Helhum\DotEnvConnector\Adapter;

use Helhum\DotEnvConnector\DotEnvVars;
use Symfony\Component\Dotenv\Dotenv;

class SymfonyLoadEnv implements DotEnvVars
{
public function exposeToEnvironment(string $dotEnvFile): void
{
if (file_exists($dotEnvFile)) {
$dotEnv = new Dotenv();
$dotEnv->usePutenv();
$dotEnv->loadEnv($dotEnvFile);
}
}
}
9 changes: 6 additions & 3 deletions src/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
];

/**
Expand Down Expand Up @@ -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:
Expand Down
9 changes: 9 additions & 0 deletions src/DotEnvVars.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php
declare(strict_types=1);

namespace Helhum\DotEnvConnector;

interface DotEnvVars
{
public function exposeToEnvironment(string $dotEnvFile): void;
}
24 changes: 12 additions & 12 deletions src/IncludeFile.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@
use Composer\Autoload\ClassLoader;
use Composer\Composer;
use Composer\Util\Filesystem;
use Helhum\DotEnvConnector\Adapter\SymfonyDotEnv;

class IncludeFile
{
private const defaultTemplate = __DIR__ . '/../res/PHP/dotenv-include.php.tmpl';

/**
* @var Config
*/
Expand Down Expand Up @@ -43,25 +46,25 @@ class IncludeFile
*/
private $filesystem;

public function __construct(Config $config, $loader, $includeFile = '', $includeFileTemplate = '', Filesystem $filesystem = null)
public function __construct(Config $config, ClassLoader $loader, string $includeFile = '', string $includeFileTemplate = null, Filesystem $filesystem = null)
{
$this->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;
}
Expand All @@ -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;
}
Expand Down
15 changes: 8 additions & 7 deletions tests/Unit/IncludeFileTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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();
Expand All @@ -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();
Expand All @@ -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();
Expand All @@ -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();
Expand All @@ -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';
Expand Down

0 comments on commit a18cede

Please sign in to comment.