Skip to content

Commit

Permalink
Added support for using environment variables in INI files
Browse files Browse the repository at this point in the history
  • Loading branch information
richard.gooding committed Jul 23, 2015
1 parent 7c3de1d commit f37904a
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 12 deletions.
64 changes: 52 additions & 12 deletions src/Provider/Ini/IniConfigProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,54 +6,69 @@
class IniConfigProvider extends AbstractConfigProvider
{
/**
* @param null|string $file Full path of ini file to create configuration from
* @param null|string $file Full path of ini file to create configuration from
* @param bool $parseEnv If true then parse environment variables in the INI file
*/
public function __construct($file = null)
public function __construct($file = null, $parseEnv = false)
{
if($file !== null)
{
$this->loadFile($file);
$this->loadFile($file, $parseEnv);
}
}

/**
* Add items from an ini file to the configuration
*
* @param string $fullPath full path to the ini file to load
* @param bool $parseEnv If true then parse environment variables in the INI file
*
* @return $this
* @throws \RuntimeException
*/
public function loadFile($fullPath)
public function loadFile($fullPath, $parseEnv = false)
{
if(!file_exists($fullPath))
{
throw new \RuntimeException("Config file '$fullPath' could not be found");
}

$data = parse_ini_file($fullPath, true);

if(!$data)
if($parseEnv)
{
throw new \RuntimeException(
"The ini file '$fullPath' is corrupt or invalid"
);
$this->loadString(file_get_contents($fullPath), true);
}
else
{
$data = parse_ini_file($fullPath, true);

if(!$data)
{
throw new \RuntimeException(
"The ini file '$fullPath' is corrupt or invalid"
);
}

$this->_buildFromData($data);
}

$this->_buildFromData($data);
return $this;
}

/**
* Add items from an ini string to the configuration
*
* @param string $iniString valid ini string
* @param bool $parseEnv If true then parse environment variables in the INI file
*
* @return $this
* @throws \RuntimeException
*/
public function loadString($iniString)
public function loadString($iniString, $parseEnv = false)
{
if($parseEnv)
{
$iniString = $this->_parseEnvVars($iniString);
}
$data = parse_ini_string($iniString, true);

if(!$data)
Expand Down Expand Up @@ -87,4 +102,29 @@ protected function _buildFromData(array $iniData)
}
}
}

/**
* Parse environment variable markers in a string and replace them with the
* variable's value.
* Variables are expected to be in this format: {{ENV:VARNAME:defaultValue}}
* The ":defaultValue" part is optional and defaults to an empty string
*
* @param string $iniString
*
* @return string
*/
private function _parseEnvVars($iniString)
{
return preg_replace_callback(
'/{{ENV:([0-9A-Za-z]*)(:([^{}]*))?}}/',
function ($matches)
{
$varName = $matches[1];
$default = isset($matches[3]) ? $matches[3] : '';
$value = getenv($varName);
return $value === false ? $default : $value;
},
$iniString
);
}
}
15 changes: 15 additions & 0 deletions testData/envtest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
invalid_item = will not be processed

[default]
item = value
var1 = {{ENV:TESTVAR1}}
var2 = {{ENV:TESTVAR2:defaultvalue}}
var1and2 = {{ENV:TESTVAR1}}-{{ENV:TESTVAR2}}
nonexistentDefault = {{ENV:NONEXISTENT:defaultValue}}
nonexistentNoDefault = {{ENV:NONEXISTENT}}

[database]
username = root
password = "fjkh%$(@££!£!@fwwejg"
hostname = localhost
database = packaged
94 changes: 94 additions & 0 deletions tests/IniConfigProviderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,98 @@ public function testLoadString()
$provider->loadString(file_get_contents($file));
$this->assertEquals("packaged", $provider->getItem("database", "database"));
}

public function testLoadFileEnv()
{
putenv('TESTVAR1=fileTestValue1');
putenv('TESTVAR2=fileTestValue2');

$file = dirname(__DIR__) . '/testData/envtest.ini';
$provider = $this->getConfigProvider();
$provider->loadFile($file, true);

$this->assertEquals(
'fileTestValue1',
$provider->getItem('default', 'var1')
);
$this->assertEquals(
'fileTestValue2',
$provider->getItem('default', 'var2')
);
$this->assertEquals(
'fileTestValue1-fileTestValue2',
$provider->getItem('default', 'var1and2')
);
$this->assertEquals(
'defaultValue',
$provider->getItem('default', 'nonexistentDefault')
);
$this->assertEquals(
'',
$provider->getItem('default', 'nonexistentNoDefault')
);
}

public function testLoadStringEnv()
{
putenv('TESTVAR1=stringTestValue1');
putenv('TESTVAR2=stringTestValue2');

$file = dirname(__DIR__) . '/testData/envtest.ini';
$provider = $this->getConfigProvider();
$provider->loadString(file_get_contents($file), true);

$this->assertEquals(
'stringTestValue1',
$provider->getItem('default', 'var1')
);
$this->assertEquals(
'stringTestValue2',
$provider->getItem('default', 'var2')
);
$this->assertEquals(
'stringTestValue1-stringTestValue2',
$provider->getItem('default', 'var1and2')
);
$this->assertEquals(
'defaultValue',
$provider->getItem('default', 'nonexistentDefault')
);
$this->assertEquals(
'',
$provider->getItem('default', 'nonexistentNoDefault')
);
}

public function testLoadFileConstructEnv()
{
putenv('TESTVAR1=constructTestValue1');
putenv('TESTVAR2=constructTestValue2');

$file = dirname(__DIR__) . '/testData/envtest.ini';
$provider = new \Packaged\Config\Provider\Ini\IniConfigProvider(
$file, true
);

$this->assertEquals(
'constructTestValue1',
$provider->getItem('default', 'var1')
);
$this->assertEquals(
'constructTestValue2',
$provider->getItem('default', 'var2')
);
$this->assertEquals(
'constructTestValue1-constructTestValue2',
$provider->getItem('default', 'var1and2')
);
$this->assertEquals(
'defaultValue',
$provider->getItem('default', 'nonexistentDefault')
);
$this->assertEquals(
'',
$provider->getItem('default', 'nonexistentNoDefault')
);
}
}

0 comments on commit f37904a

Please sign in to comment.