Skip to content
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

Environment variables object #208

Closed
Closed
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
163 changes: 163 additions & 0 deletions src/EnvironmentVariables.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
<?php

namespace Dotenv;

use ArrayAccess;

/**
* @author Nikola Posa <[email protected]>
*/
class EnvironmentVariables implements ArrayAccess
{
/**
* @var bool
*/
protected $immutable;

protected function __construct($immutable)
{
$this->immutable = $immutable;
}

/**
* Creates EnvironmentVariables instance.
*
* @return EnvironmentVariables
*/
public static function create()
{
return new static(false);
}

/**
* Creates immutable EnvironmentVariables instance.
*
* @return EnvironmentVariables
*/
public static function createImmutable()
{
return new static(true);
}

/**
* Tells whether environment variable has been defined.
*
* @param string $name
*
* @return bool
*/
public function has($name)
{
return !is_null($this->get($name));
}

/**
* Search the different places for environment variables and return first value found.
*
* @param string $name
*
* @return string|null
*/
public function get($name)
{
switch (true) {
case array_key_exists($name, $_ENV):
return $_ENV[$name];
case array_key_exists($name, $_SERVER):
return $_SERVER[$name];
default:
$value = getenv($name);
return $value === false ? null : $value; // switch getenv default to null
}
}

/**
* Set an environment variable.
*
* This is done using:
* - putenv,
* - $_ENV,
* - $_SERVER.
*
* The environment variable value is stripped of single and double quotes.
*
* @param string $name
* @param string|null $value
*
* @return void
*/
public function set($name, $value = null)
{
// Don't overwrite existing environment variables if we're immutable
// Ruby's dotenv does this with `ENV[key] ||= value`.
if ($this->immutable && $this->has($name)) {
return;
}

// If PHP is running as an Apache module and an existing
// Apache environment variable exists, overwrite it
if (function_exists('apache_getenv') && function_exists('apache_setenv') && apache_getenv($name)) {
apache_setenv($name, $value);
}

putenv("$name=$value");
$_ENV[$name] = $value;
$_SERVER[$name] = $value;
}

/**
* Clear an environment variable.
*
* This is done using:
* - putenv,
* - unset($_ENV, $_SERVER).
*
* @param string $name
*
* @see setEnvironmentVariable()
*
* @return void
*/
public function clear($name)
{
// Don't clear anything if we're immutable.
if ($this->immutable) {
return;
}

putenv($name);
unset($_ENV[$name], $_SERVER[$name]);
}

/**
* {@inheritdoc}
*/
public function offsetExists($offset)
{
return $this->has($offset);
}

/**
* {@inheritdoc}
*/
public function offsetGet($offset)
{
return $this->get($offset);
}

/**
* {@inheritdoc}
*/
public function offsetSet($offset, $value)
{
$this->set($offset, $value);
}

/**
* {@inheritdoc}
*/
public function offsetUnset($offset)
{
$this->clear($offset);
}
}
62 changes: 9 additions & 53 deletions src/Loader.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,9 @@ class Loader
protected $filePath;

/**
* Are we immutable?
*
* @var bool
* @var EnvironmentVariables
*/
protected $immutable;
protected $environmentVariables;

/**
* Create a new loader instance.
Expand All @@ -39,7 +37,7 @@ class Loader
public function __construct($filePath, $immutable = false)
{
$this->filePath = $filePath;
$this->immutable = $immutable;
$this->setImmutable($immutable);
}

/**
Expand All @@ -50,21 +48,13 @@ public function __construct($filePath, $immutable = false)
*/
public function setImmutable($immutable = false)
{
$this->immutable = $immutable;
$this->environmentVariables = $immutable
? EnvironmentVariables::createImmutable()
: EnvironmentVariables::create();

return $this;
}

/**
* Set immutable value.
*
* @return bool
*/
public function getImmutable()
{
return $this->immutable;
}

/**
* Load `.env` file in given directory.
*
Expand Down Expand Up @@ -324,15 +314,7 @@ protected function beginsWithAQuote($value)
*/
public function getEnvironmentVariable($name)
{
switch (true) {
case array_key_exists($name, $_ENV):
return $_ENV[$name];
case array_key_exists($name, $_SERVER):
return $_SERVER[$name];
default:
$value = getenv($name);
return $value === false ? null : $value; // switch getenv default to null
}
return $this->environmentVariables->get($name);
}

/**
Expand All @@ -354,24 +336,7 @@ public function setEnvironmentVariable($name, $value = null)
{
list($name, $value) = $this->normaliseEnvironmentVariable($name, $value);

// Don't overwrite existing environment variables if we're immutable
// Ruby's dotenv does this with `ENV[key] ||= value`.
if ($this->immutable && $this->getEnvironmentVariable($name) !== null) {
return;
}

// If PHP is running as an Apache module and an existing
// Apache environment variable exists, overwrite it
if (function_exists('apache_getenv') && function_exists('apache_setenv') && apache_getenv($name)) {
apache_setenv($name, $value);
}

if (function_exists('putenv')) {
putenv("$name=$value");
}

$_ENV[$name] = $value;
$_SERVER[$name] = $value;
$this->environmentVariables->set($name, $value);
}

/**
Expand All @@ -392,15 +357,6 @@ public function setEnvironmentVariable($name, $value = null)
*/
public function clearEnvironmentVariable($name)
{
// Don't clear anything if we're immutable.
if ($this->immutable) {
return;
}

if (function_exists('putenv')) {
putenv($name);
}

unset($_ENV[$name], $_SERVER[$name]);
$this->environmentVariables->clear($name);
}
}
103 changes: 103 additions & 0 deletions tests/Dotenv/EnvironmentVariablesTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
<?php

use Dotenv\EnvironmentVariables;
use Dotenv\Loader;

class EnvironmentVariablesTest extends PHPUnit_Framework_TestCase
{
protected function setUp()
{
$loader = new Loader(dirname(__DIR__) . '/fixtures/env/.env');
$loader->load();
}

public function testCheckingWhetherVariableExists()
{
$envVars = EnvironmentVariables::create();

$this->assertTrue($envVars->has('FOO'));
$this->assertFalse($envVars->has('NON_EXISTING_VARIABLE'));
}

public function testGettingVariableByName()
{
$envVars = EnvironmentVariables::create();

$this->assertSame('bar', $envVars->get('FOO'));
}

public function testSettingVariable()
{
$envVars = EnvironmentVariables::create();

$this->assertSame('bar', $envVars->get('FOO'));

$envVars->set('FOO', 'new');

$this->assertSame('new', $envVars->get('FOO'));
}

public function testClearingVariable()
{
$envVars = EnvironmentVariables::create();

$envVars->clear('FOO');

$this->assertFalse($envVars->has('FOO'));
}

public function testCannotSetVariableOnImmutableInstance()
{
$envVars = EnvironmentVariables::createImmutable();

$this->assertSame('bar', $envVars->get('FOO'));

$envVars->set('FOO', 'new');

$this->assertSame('bar', $envVars->get('FOO'));
}

public function testCannotClearVariableOnImmutableInstance()
{
$envVars = EnvironmentVariables::createImmutable();

$envVars->clear('FOO');

$this->assertTrue($envVars->has('FOO'));
}

public function testCheckingWhetherVariableExistsUsingArrayNotation()
{
$envVars = EnvironmentVariables::create();

$this->assertTrue(isset($envVars['FOO']));
$this->assertFalse(isset($envVars['NON_EXISTING_VARIABLE']));
}

public function testGettingVariableByNameUsingArrayNotation()
{
$envVars = EnvironmentVariables::create();

$this->assertSame('bar', $envVars['FOO']);
}

public function testSettingVariableUsingArrayNotation()
{
$envVars = EnvironmentVariables::create();

$this->assertSame('bar', $envVars['FOO']);

$envVars['FOO'] = 'new';

$this->assertSame('new', $envVars['FOO']);
}

public function testClearingVariableUsingArrayNotation()
{
$envVars = EnvironmentVariables::create();

unset($envVars['FOO']);

$this->assertFalse(isset($envVars['FOO']));
}
}
Loading