Skip to content

Commit

Permalink
Prefix calls to getenv() during config resolution
Browse files Browse the repository at this point in the history
  • Loading branch information
paulbalandan committed Apr 23, 2021
1 parent c83a9cf commit 6c90cab
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 75 deletions.
5 changes: 4 additions & 1 deletion system/Config/BaseConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ protected function initEnvValue(&$property, string $name, string $prefix, string
protected function getEnvValue(string $property, string $prefix, string $shortPrefix)
{
$shortPrefix = ltrim($shortPrefix, '\\');

switch (true)
{
case array_key_exists("{$shortPrefix}.{$property}", $_ENV):
Expand All @@ -145,7 +146,9 @@ protected function getEnvValue(string $property, string $prefix, string $shortPr
case array_key_exists("{$prefix}.{$property}", $_SERVER):
return $_SERVER["{$prefix}.{$property}"];
default:
$value = getenv($property);
$value = getenv("{$shortPrefix}.{$property}");
$value = $value === false ? getenv("{$prefix}.{$property}") : $value;

return $value === false ? null : $value;
}
}
Expand Down
104 changes: 36 additions & 68 deletions tests/system/Config/BaseConfigTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,8 @@

class BaseConfigTest extends CIUnitTestCase
{

protected $fixturesFolder;

//--------------------------------------------------------------------

protected function setUp(): void
{
parent::setUp();
Expand All @@ -37,21 +34,16 @@ protected function setUp(): void
}
}

//--------------------------------------------------------------------

public function testBasicValues()
{
$dotenv = new DotEnv($this->fixturesFolder, '.env');
$dotenv->load();
$config = new SimpleConfig();

$this->assertEquals('bar', $config->FOO);
// empty treated as boolean false
$this->assertEquals(false, $config->echo);
// 'true' should be treated as boolean true
$this->assertNull($config->FOO);
$this->assertSame('', $config->echo);
$this->assertTrue($config->foxtrot);
// numbers should be treated properly
$this->assertEquals(18, $config->golf);
$this->assertSame(18, $config->golf);
}

/**
Expand All @@ -68,12 +60,10 @@ public function testServerValues()
$dotenv->load();
$config = new SimpleConfig();

$this->assertEquals(123, $config->shortie);
$this->assertEquals(456, $config->longie);
$this->assertSame('123', $config->shortie);
$this->assertSame('456', $config->longie);
}

//--------------------------------------------------------------------

public function testEnvironmentOverrides()
{
$dotenv = new DotEnv($this->fixturesFolder, '.env');
Expand All @@ -82,81 +72,69 @@ public function testEnvironmentOverrides()
$config = new SimpleConfig();

// override config with ENV var
$this->assertEquals('pow', $config->alpha);
$this->assertSame('pow', $config->alpha);
// config should not be over-written by wrongly named ENV var
$this->assertEquals('three', $config->charlie);
$this->assertSame('three', $config->charlie);
// override config with shortPrefix ENV var
$this->assertEquals('hubbahubba', $config->delta);
$this->assertSame('hubbahubba', $config->delta);
// incorrect env name should not inject property
$this->assertObjectNotHasAttribute('notthere', $config);
// same ENV var as property, but not namespaced, still over-rides
$this->assertEquals('kazaam', $config->bravo);
// empty ENV var should not affect config setting
$this->assertEquals('pineapple', $config->fruit);
$this->assertSame('pineapple', $config->fruit);
// non-empty ENV var should overrideconfig setting
$this->assertEquals('banana', $config->dessert);
$this->assertSame('banana', $config->dessert);
// null property should not be affected
$this->assertNull($config->QEMPTYSTR);
}

//--------------------------------------------------------------------

public function testPrefixedValues()
{
$dotenv = new DotEnv($this->fixturesFolder, '.env');
$dotenv->load();

$config = new SimpleConfig();

$this->assertEquals('baz', $config->onedeep);
$this->assertSame('baz', $config->onedeep);
}

//--------------------------------------------------------------------

public function testPrefixedArrayValues()
{
$dotenv = new DotEnv($this->fixturesFolder, '.env');
$dotenv->load();

$config = new SimpleConfig();

$this->assertEquals('ci4', $config->default['name']);
$this->assertEquals('Malcolm', $config->crew['captain']);
$this->assertEquals('Spock', $config->crew['science']);
$this->assertFalse(array_key_exists('pilot', $config->crew));
$this->assertSame('ci4', $config->default['name']);
$this->assertSame('Malcolm', $config->crew['captain']);
$this->assertSame('Spock', $config->crew['science']);
$this->assertArrayNotHasKey('pilot', $config->crew);
$this->assertTrue($config->crew['comms']);
$this->assertFalse($config->crew['doctor']);
}

//--------------------------------------------------------------------

public function testArrayValues()
{
$dotenv = new DotEnv($this->fixturesFolder, '.env');
$dotenv->load();

$config = new SimpleConfig();

$this->assertEquals('complex', $config->simple['name']);
$this->assertEquals('foo', $config->first);
$this->assertEquals('bar', $config->second);
$this->assertSame('complex', $config->simple['name']);
$this->assertSame('foo', $config->first);
$this->assertSame('bar', $config->second);
}

//--------------------------------------------------------------------

public function testSetsDefaultValues()
{
$dotenv = new DotEnv($this->fixturesFolder, 'commented.env');
$dotenv->load();

$config = new SimpleConfig();

$this->assertEquals('foo', $config->first);
$this->assertEquals('bar', $config->second);
$this->assertSame('foo', $config->first);
$this->assertSame('bar', $config->second);
}

//--------------------------------------------------------------------

/**
* @runInSeparateProcess
* @preserveGlobalState disabled
Expand All @@ -168,12 +146,10 @@ public function testSetsDefaultValuesEncryptionUsingHex2Bin()
$config = new Encryption();

// override config with ENV var
$this->assertEquals('f699c7fd18a8e082d0228932f3acd40e1ef5ef92efcedda32842a211d62f0aa6', bin2hex($config->key));
$this->assertEquals('OpenSSL', $config->driver);
$this->assertSame('f699c7fd18a8e082d0228932f3acd40e1ef5ef92efcedda32842a211d62f0aa6', bin2hex($config->key));
$this->assertSame('OpenSSL', $config->driver);
}

//--------------------------------------------------------------------

/**
* @runInSeparateProcess
* @preserveGlobalState disabled
Expand All @@ -184,37 +160,31 @@ public function testSetDefaultValuesEncryptionUsingBase64()
$dotenv->load();
$config = new Encryption('base64');

$this->assertEquals('L40bKo6b8Nu541LeVeZ1i5RXfGgnkar42CPTfukhGhw=', base64_encode($config->key));
$this->assertEquals('OpenSSL', $config->driver);
$this->assertSame('L40bKo6b8Nu541LeVeZ1i5RXfGgnkar42CPTfukhGhw=', base64_encode($config->key));
$this->assertSame('OpenSSL', $config->driver);
}

//--------------------------------------------------------------------

public function testSetsDefaultValuesHex2Bin()
{
$dotenv = new DotEnv($this->fixturesFolder, 'commented.env');
$dotenv->load();
$config = new Encryption();

// override config with ENV var
$this->assertEquals('84cf2c0811d5daf9e1c897825a3debce91f9a33391e639f72f7a4740b30675a2', bin2hex($config->key));
$this->assertEquals('MCrypt', $config->driver);
$this->assertSame('84cf2c0811d5daf9e1c897825a3debce91f9a33391e639f72f7a4740b30675a2', bin2hex($config->key));
$this->assertSame('MCrypt', $config->driver);
}

//--------------------------------------------------------------------

public function testSetDefaultValuesBase64()
{
$dotenv = new DotEnv($this->fixturesFolder, 'commented.env');
$dotenv->load();
$config = new Encryption('base64');

$this->assertEquals('Psf8bUHRh1UJYG2M7e+5ec3MdjpKpzAr0twamcAvOcI=', base64_encode($config->key));
$this->assertEquals('MCrypt', $config->driver);
$this->assertSame('Psf8bUHRh1UJYG2M7e+5ec3MdjpKpzAr0twamcAvOcI=', base64_encode($config->key));
$this->assertSame('MCrypt', $config->driver);
}

//--------------------------------------------------------------------

public function testRecognizesLooseValues()
{
$dotenv = new DotEnv($this->fixturesFolder, 'loose.env');
Expand All @@ -224,12 +194,10 @@ public function testRecognizesLooseValues()

$this->assertEquals(0, $config->QZERO);
$this->assertSame('0', $config->QZEROSTR);
$this->assertEquals(' ', $config->QEMPTYSTR);
$this->assertSame(' ', $config->QEMPTYSTR);
$this->assertFalse($config->QFALSE);
}

//--------------------------------------------------------------------

public function testRegistrars()
{
$config = new RegistrarConfig();
Expand All @@ -239,13 +207,13 @@ public function testRegistrars()
$method();

// no change to unmodified property
$this->assertEquals('bar', $config->foo);
$this->assertSame('bar', $config->foo);
// add to an existing array property
$this->assertEquals(['baz', 'first', 'second'], $config->bar);
$this->assertSame(['baz', 'first', 'second'], $config->bar);
// add a new property
$this->assertEquals('nice', $config->format);
$this->assertSame('nice', $config->format);
// add a new array property
$this->assertEquals(['apple', 'banana'], $config->fruit);
$this->assertSame(['apple', 'banana'], $config->fruit);
}

public function testBadRegistrar()
Expand All @@ -259,7 +227,7 @@ public function testBadRegistrar()
$method = $this->getPrivateMethodInvoker($config, 'registerProperties');
$method();

$this->assertEquals('bar', $config->foo);
$this->assertSame('bar', $config->foo);
}

public function testNotEnabled()
Expand All @@ -274,7 +242,7 @@ public function testNotEnabled()
$method = $this->getPrivateMethodInvoker($config, 'registerProperties');
$method();

$this->assertEquals($expected, $config::$registrars);
$this->assertSame($expected, $config::$registrars);
}

public function testDidDiscovery()
Expand All @@ -289,7 +257,7 @@ public function testDidDiscovery()
$method = $this->getPrivateMethodInvoker($config, 'registerProperties');
$method();

$this->assertEquals(true, $this->getPrivateProperty($config, 'didDiscovery'));
$this->assertSame(true, $this->getPrivateProperty($config, 'didDiscovery'));
}

}
2 changes: 1 addition & 1 deletion tests/system/Config/DotEnvTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ public function testNamespacedVariables()
$dotenv = new Dotenv($this->fixturesFolder, '.env');
$dotenv->load();

$this->assertEquals('complex', $_SERVER['simple.name']);
$this->assertEquals('complex', $_SERVER['SimpleConfig.simple.name']);
}

//--------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion tests/system/Config/fixtures/.env
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ NULL=

SimpleConfig.onedeep=baz
SimpleConfig.default.name=ci4
simple.name=complex
SimpleConfig.simple.name=complex

# for environment override testing
SimpleConfig.alpha=pow
Expand Down
8 changes: 4 additions & 4 deletions tests/system/Config/fixtures/loose.env
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
QZERO=0
QZEROSTR="0"
QEMPTYSTR=" "
QFALSE=false
SimpleConfig.QZERO=0
SimpleConfig.QZEROSTR="0"
SimpleConfig.QEMPTYSTR=" "
SimpleConfig.QFALSE=false
1 change: 1 addition & 0 deletions user_guide_src/source/changelogs/v4.1.2.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Changes:
- Entity. Timestamp casting now throws an exception when an invalid value is passed
- ``Entity::castAsJson`` uses external cast handler ``JsonCast::get``.
- ``Entity::mutateDate`` uses external cast handler ``DatetimeCast::get``.
- In order for ``Config\**`` classes to get their respective properties' values from the ``.env``, it is now necessary to namespace the property with the name of the class. Previously, the property names are enough but now disallowed because it can get system environment variables, like ``PATH``.

Deprecations:

Expand Down

0 comments on commit 6c90cab

Please sign in to comment.