Skip to content

Commit 0c569c5

Browse files
committed
Added environment variable overrides
1 parent ef43ee6 commit 0c569c5

File tree

5 files changed

+129
-15
lines changed

5 files changed

+129
-15
lines changed

README.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ Open them up and take a look around.
7272

7373
> A quick word on XML. Why is he using XML? It's not cool anymore! YAML or JSON would make me feel much better.
7474
>
75-
> The answer is that neither YAML, JSON, nor PHP files are self documenting. I'm sure there are tools out there that might allow you to do some of that but there is nothing out there that compares to what is available for XML. I am a firm believer that some for of introspection which can be used for error detection or, more importantly, code completion, significantly reduce the amount of startup time. It simply requires less memorizing and less copy-and-pasting. But that said, if you look in the /lib directory you will find that the intention is to support all of those formats for the masochists out there. I just haven't done it yet.
75+
> The answer is that neither YAML, JSON, nor PHP files are self documenting. I'm sure there are tools out there that might allow you to do some of that but there is nothing out there that compares to what is available for XML. I am a firm believer that when introspection is be used for error detection or, more importantly, code completion, it significantly reduce the amount of time spent on getting things to work. It simply requires less memorizing and less copy-and-pasting. But that said, if you look in the /lib directory you will find that the intention is to support all of those formats for the masochists out there.
7676
7777
Take a look inside the `magium-configuration.xml` file. Much of it is, I believe, self explanatory. However, note the `persistenceConfiguration` and `cache` nodes. Those are converted to arrays and passed into the `Zend\Db\Adapter\Adapter` and `Zend\Cache\StorageFactory` classes, respectively. Note, also, the `contextConfigurationFile` node. That contains a reference to the next configuration file.
7878

@@ -219,6 +219,23 @@ On the element side, looking at `website/contact/address`, you can see that ther
219219
* datetime (for future use)
220220

221221
You can also see that the individual elements can be populated from a source when looking at `website/contact/state`. These sources can be used to prepopulate text fields or provide select options. See the [source code](lib/Source) for a full list.
222+
223+
#### Environment Variable Overrides
224+
225+
You can also override the values in your `magium-configuration.xml` file by using environment variables. This allows you to change the base settings, such as the local cache adapter host name, based off of the environment that you are running in. For example, your development environment might have a Redis adapter sitting on the `localhost` but in production it lives at `cache.myhost`. To handle this, set the value for `cache/options/server` to `cache.myhost` in the source code (to default to production). Then in your *development* environment add this to your webserver config (or something like it):
226+
227+
```
228+
location ~ \.php$ {
229+
fastcgi_pass unix:/your_sock_location/nginxFastCGI.sock;
230+
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
231+
fastcgi_param MCM_CACHE_OPTIONS_SERVER=localhost;
232+
include fastcgi_params;
233+
}
234+
```
235+
236+
Any value in the `magium-configuration.xml` file can be overridden and replaced with an environment variable by creating the variable with the prefix `MCM_` and appending the node path to the node that you want to change.
237+
238+
For example, looking at what we did above, it was for the configuration node `cache/options/server` and so we named our environment variable `MCM_CACHE_OPTIONS_SERVER`.
222239

223240
#### Configuring Your Application
224241

composer.json

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,26 +16,31 @@
1616
}
1717
},
1818
"require-dev": {
19-
"phpunit/phpunit": "~5.7",
19+
"phpunit/phpunit": "~6",
2020
"zendframework/zend-psr7bridge": "^0.2",
2121
"zendframework/zend-di": "^2.6",
22-
"guzzlehttp/psr7": "^1.4"
22+
"guzzlehttp/psr7": "^1.4",
23+
"zendframework/zend-view": "^2",
24+
"zendframework/zend-http": "^2",
25+
"zendframework/zend-form": "^2",
26+
"zendframework/zend-i18n": "^2",
27+
"zendframework/zend-json": "^2"
2328
},
2429
"require": {
2530
"zendframework/zend-cache": "^2.0",
2631
"psr/container": "^1",
2732
"zendframework/zend-db": "^2.0",
2833
"symfony/console": "~2.3|~3.0",
2934
"psr/http-message": "^1.0",
30-
"symfony/yaml": "^2",
35+
"symfony/yaml": "^2"
36+
},
37+
"suggest": {
38+
"zendframework/zend-psr7bridge": "^0.1",
3139
"zendframework/zend-view": "^2",
3240
"zendframework/zend-http": "^2",
3341
"zendframework/zend-form": "^2",
3442
"zendframework/zend-i18n": "^2",
3543
"zendframework/zend-json": "^2"
36-
},
37-
"suggest": {
38-
"zendframework/zend-psr7bridge": "^0.1"
3944
},
4045
"bin": ["bin/magium-configuration"]
4146
}

lib/MagiumConfigurationFactory.php

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
use Magium\Configuration\Config\BuilderFactory;
66
use Magium\Configuration\Config\BuilderFactoryInterface;
77
use Magium\Configuration\Config\BuilderInterface;
8-
use Magium\Configuration\Config\Repository\ConfigurationRepository;
98
use Magium\Configuration\Config\Context;
109
use Magium\Configuration\Config\MissingConfigurationException;
10+
use Magium\Configuration\Config\Repository\ConfigurationRepository;
1111
use Magium\Configuration\File\Context\AbstractContextConfigurationFile;
1212
use Magium\Configuration\Manager\CacheFactory;
1313
use Magium\Configuration\Manager\Manager;
@@ -56,6 +56,59 @@ public function __construct($magiumConfigurationFile = null, $context = Configur
5656
$this->baseDir = dirname($this->file);
5757
chdir($this->baseDir);
5858
$this->xml = simplexml_load_file($magiumConfigurationFile);
59+
$this->overrideWithEnvironmentVariables();
60+
}
61+
62+
protected function overrideWithEnvironmentVariables()
63+
{
64+
$document = dom_import_simplexml($this->xml)->ownerDocument;
65+
$xpath = new \DOMXPath($document);
66+
$elements = $xpath->query('//*');
67+
foreach ($elements as $element) {
68+
if ($element instanceof \DOMElement) {
69+
$paths = [];
70+
do {
71+
$paths[] = $element->nodeName;
72+
} while ($element = $element->parentNode);
73+
74+
// Get rid of the base node and base document. They mean nothing to us.
75+
array_pop($paths);
76+
array_pop($paths);
77+
if ($paths) {
78+
$paths = array_reverse($paths);
79+
$path = implode('/', $paths);
80+
$value = $this->getEnvironmentVariableOverride($path);
81+
if ($value !== null) {
82+
foreach ($paths as &$path) {
83+
$path = 's:' . $path;
84+
}
85+
$path = implode('/', $paths);
86+
$xpathExpression = '/s:magiumBase/' . $path;
87+
$this->xml->registerXPathNamespace('s', 'http://www.magiumlib.com/BaseConfiguration');
88+
$simpleXmlElement = $this->xml->xpath($xpathExpression);
89+
if ($simpleXmlElement) {
90+
$simpleXmlElement = $simpleXmlElement[0];
91+
$simpleXmlElement[0] = $value; // self reference
92+
}
93+
}
94+
}
95+
96+
}
97+
}
98+
}
99+
100+
/**
101+
* @return \SimpleXMLElement
102+
*/
103+
104+
public function getXml()
105+
{
106+
return $this->xml;
107+
}
108+
109+
public function getMagiumConfigurationFilePath()
110+
{
111+
return $this->file;
59112
}
60113

61114
protected static function getInstance($magiumConfigurationFile = null, $context = ConfigurationRepository::CONTEXT_DEFAULT)
@@ -94,6 +147,16 @@ public function setContext($context)
94147
$this->context = $context;
95148
}
96149

150+
public function getEnvironmentVariableOverride($path)
151+
{
152+
$pathTranslated = 'MCM_' . str_replace('/', '_', strtoupper($path));
153+
$value = getenv($pathTranslated);
154+
if (!$value) {
155+
return null;
156+
}
157+
return $value;
158+
}
159+
97160
protected function buildContextFile()
98161
{
99162
chdir($this->baseDir);

tests/Factory/FactoryTest.php

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
use Magium\Configuration\Config\Context;
77
use Magium\Configuration\Config\InvalidConfigurationLocationException;
88
use Magium\Configuration\Config\MissingConfigurationException;
9-
use Magium\Configuration\Config\Repository\ConfigurationRepository;
10-
use Magium\Configuration\File\Configuration\ConfigurationFileRepository;
119
use Magium\Configuration\File\Context\AbstractContextConfigurationFile;
1210
use Magium\Configuration\File\Context\XmlFile;
1311
use Magium\Configuration\InvalidConfigurationException;
@@ -28,6 +26,7 @@ protected function setFile($contents = '<config />', $filename = self::CONFIG)
2826
{
2927
$this->configFile[$filename] = __DIR__ . '/../../' . $filename;
3028
file_put_contents($this->configFile[$filename], $contents);
29+
return $this->configFile[$filename];
3130
}
3231

3332
protected function tearDown()
@@ -52,7 +51,29 @@ public function testExistingConfigFile()
5251
{
5352
$this->setFile();
5453
$path = realpath($this->configFile[self::CONFIG]);
55-
new MagiumConfigurationFactory($path);
54+
$factory = new MagiumConfigurationFactory($path);
55+
56+
self::assertEquals($path, $factory->getMagiumConfigurationFilePath());
57+
}
58+
59+
60+
public function testEnvironmentVariableOverrideReturnsValue()
61+
{
62+
$this->setFile();
63+
$factory = new MagiumConfigurationFactory();
64+
putenv('MCM_CACHE_OPTIONS_SERVER=boogers');
65+
$value = $factory->getEnvironmentVariableOverride('cache/options/server');
66+
self::assertEquals('boogers', $value);
67+
}
68+
69+
public function testEnvironmentVariableOverrideXmlValue()
70+
{
71+
putenv('MCM_CACHE_OPTIONS_SERVER=boogers');
72+
$this->setFile(file_get_contents(__DIR__ . '/magium-configuration.xml'));
73+
$factory = new MagiumConfigurationFactory();
74+
$xml = $factory->getXml();
75+
$value = (string)$xml->cache->options->server;
76+
self::assertEquals('boogers', $value);
5677
}
5778

5879
public function testValidateDocumentSucceeds()
@@ -223,8 +244,10 @@ public function testValidateDocumentFailsWithImproperConfigFile()
223244

224245
public function testFindExistingConfigFile()
225246
{
226-
$this->setFile();
227-
new MagiumConfigurationFactory();
247+
$filename = realpath($this->setFile());
248+
$factory = new MagiumConfigurationFactory();
249+
250+
self::assertEquals($filename, $factory->getMagiumConfigurationFilePath());
228251
}
229252
public function testInvalidConfigFileThrowsException()
230253
{
Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
<?xml version="1.0" encoding="UTF-8" ?>
2-
<magium xmlns="http://www.magiumlib.com/BaseConfiguration">
2+
<magiumBase xmlns="http://www.magiumlib.com/BaseConfiguration">
33
<persistenceConfiguration>
44
<driver></driver>
55
<database></database>
66
</persistenceConfiguration>
77
<contextConfigurationFile file="" type="xml"/>
8-
</magium>
8+
<cache>
9+
<adapter>redis</adapter>
10+
<options>
11+
<server>database:6379</server>
12+
</options>
13+
</cache>
14+
</magiumBase>

0 commit comments

Comments
 (0)