Skip to content

Commit

Permalink
Added environment variable overrides
Browse files Browse the repository at this point in the history
  • Loading branch information
kschroeder committed Nov 27, 2017
1 parent ef43ee6 commit 0c569c5
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 15 deletions.
19 changes: 18 additions & 1 deletion README.md
Expand Up @@ -72,7 +72,7 @@ Open them up and take a look around.

> A quick word on XML. Why is he using XML? It's not cool anymore! YAML or JSON would make me feel much better.
>
> 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.
> 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.
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.

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

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.

#### Environment Variable Overrides

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):

```
location ~ \.php$ {
fastcgi_pass unix:/your_sock_location/nginxFastCGI.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param MCM_CACHE_OPTIONS_SERVER=localhost;
include fastcgi_params;
}
```

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.

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`.

#### Configuring Your Application

Expand Down
17 changes: 11 additions & 6 deletions composer.json
Expand Up @@ -16,26 +16,31 @@
}
},
"require-dev": {
"phpunit/phpunit": "~5.7",
"phpunit/phpunit": "~6",
"zendframework/zend-psr7bridge": "^0.2",
"zendframework/zend-di": "^2.6",
"guzzlehttp/psr7": "^1.4"
"guzzlehttp/psr7": "^1.4",
"zendframework/zend-view": "^2",
"zendframework/zend-http": "^2",
"zendframework/zend-form": "^2",
"zendframework/zend-i18n": "^2",
"zendframework/zend-json": "^2"
},
"require": {
"zendframework/zend-cache": "^2.0",
"psr/container": "^1",
"zendframework/zend-db": "^2.0",
"symfony/console": "~2.3|~3.0",
"psr/http-message": "^1.0",
"symfony/yaml": "^2",
"symfony/yaml": "^2"
},
"suggest": {
"zendframework/zend-psr7bridge": "^0.1",
"zendframework/zend-view": "^2",
"zendframework/zend-http": "^2",
"zendframework/zend-form": "^2",
"zendframework/zend-i18n": "^2",
"zendframework/zend-json": "^2"
},
"suggest": {
"zendframework/zend-psr7bridge": "^0.1"
},
"bin": ["bin/magium-configuration"]
}
65 changes: 64 additions & 1 deletion lib/MagiumConfigurationFactory.php
Expand Up @@ -5,9 +5,9 @@
use Magium\Configuration\Config\BuilderFactory;
use Magium\Configuration\Config\BuilderFactoryInterface;
use Magium\Configuration\Config\BuilderInterface;
use Magium\Configuration\Config\Repository\ConfigurationRepository;
use Magium\Configuration\Config\Context;
use Magium\Configuration\Config\MissingConfigurationException;
use Magium\Configuration\Config\Repository\ConfigurationRepository;
use Magium\Configuration\File\Context\AbstractContextConfigurationFile;
use Magium\Configuration\Manager\CacheFactory;
use Magium\Configuration\Manager\Manager;
Expand Down Expand Up @@ -56,6 +56,59 @@ public function __construct($magiumConfigurationFile = null, $context = Configur
$this->baseDir = dirname($this->file);
chdir($this->baseDir);
$this->xml = simplexml_load_file($magiumConfigurationFile);
$this->overrideWithEnvironmentVariables();
}

protected function overrideWithEnvironmentVariables()
{
$document = dom_import_simplexml($this->xml)->ownerDocument;
$xpath = new \DOMXPath($document);
$elements = $xpath->query('//*');
foreach ($elements as $element) {
if ($element instanceof \DOMElement) {
$paths = [];
do {
$paths[] = $element->nodeName;
} while ($element = $element->parentNode);

// Get rid of the base node and base document. They mean nothing to us.
array_pop($paths);
array_pop($paths);
if ($paths) {
$paths = array_reverse($paths);
$path = implode('/', $paths);
$value = $this->getEnvironmentVariableOverride($path);
if ($value !== null) {
foreach ($paths as &$path) {
$path = 's:' . $path;
}
$path = implode('/', $paths);
$xpathExpression = '/s:magiumBase/' . $path;
$this->xml->registerXPathNamespace('s', 'http://www.magiumlib.com/BaseConfiguration');
$simpleXmlElement = $this->xml->xpath($xpathExpression);
if ($simpleXmlElement) {
$simpleXmlElement = $simpleXmlElement[0];
$simpleXmlElement[0] = $value; // self reference
}
}
}

}
}
}

/**
* @return \SimpleXMLElement
*/

public function getXml()
{
return $this->xml;
}

public function getMagiumConfigurationFilePath()
{
return $this->file;
}

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

public function getEnvironmentVariableOverride($path)
{
$pathTranslated = 'MCM_' . str_replace('/', '_', strtoupper($path));
$value = getenv($pathTranslated);
if (!$value) {
return null;
}
return $value;
}

protected function buildContextFile()
{
chdir($this->baseDir);
Expand Down
33 changes: 28 additions & 5 deletions tests/Factory/FactoryTest.php
Expand Up @@ -6,8 +6,6 @@
use Magium\Configuration\Config\Context;
use Magium\Configuration\Config\InvalidConfigurationLocationException;
use Magium\Configuration\Config\MissingConfigurationException;
use Magium\Configuration\Config\Repository\ConfigurationRepository;
use Magium\Configuration\File\Configuration\ConfigurationFileRepository;
use Magium\Configuration\File\Context\AbstractContextConfigurationFile;
use Magium\Configuration\File\Context\XmlFile;
use Magium\Configuration\InvalidConfigurationException;
Expand All @@ -28,6 +26,7 @@ protected function setFile($contents = '<config />', $filename = self::CONFIG)
{
$this->configFile[$filename] = __DIR__ . '/../../' . $filename;
file_put_contents($this->configFile[$filename], $contents);
return $this->configFile[$filename];
}

protected function tearDown()
Expand All @@ -52,7 +51,29 @@ public function testExistingConfigFile()
{
$this->setFile();
$path = realpath($this->configFile[self::CONFIG]);
new MagiumConfigurationFactory($path);
$factory = new MagiumConfigurationFactory($path);

self::assertEquals($path, $factory->getMagiumConfigurationFilePath());
}


public function testEnvironmentVariableOverrideReturnsValue()
{
$this->setFile();
$factory = new MagiumConfigurationFactory();
putenv('MCM_CACHE_OPTIONS_SERVER=boogers');
$value = $factory->getEnvironmentVariableOverride('cache/options/server');
self::assertEquals('boogers', $value);
}

public function testEnvironmentVariableOverrideXmlValue()
{
putenv('MCM_CACHE_OPTIONS_SERVER=boogers');
$this->setFile(file_get_contents(__DIR__ . '/magium-configuration.xml'));
$factory = new MagiumConfigurationFactory();
$xml = $factory->getXml();
$value = (string)$xml->cache->options->server;
self::assertEquals('boogers', $value);
}

public function testValidateDocumentSucceeds()
Expand Down Expand Up @@ -223,8 +244,10 @@ public function testValidateDocumentFailsWithImproperConfigFile()

public function testFindExistingConfigFile()
{
$this->setFile();
new MagiumConfigurationFactory();
$filename = realpath($this->setFile());
$factory = new MagiumConfigurationFactory();

self::assertEquals($filename, $factory->getMagiumConfigurationFilePath());
}
public function testInvalidConfigFileThrowsException()
{
Expand Down
10 changes: 8 additions & 2 deletions tests/Factory/magium-configuration.xml
@@ -1,8 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
<magium xmlns="http://www.magiumlib.com/BaseConfiguration">
<magiumBase xmlns="http://www.magiumlib.com/BaseConfiguration">
<persistenceConfiguration>
<driver></driver>
<database></database>
</persistenceConfiguration>
<contextConfigurationFile file="" type="xml"/>
</magium>
<cache>
<adapter>redis</adapter>
<options>
<server>database:6379</server>
</options>
</cache>
</magiumBase>

0 comments on commit 0c569c5

Please sign in to comment.