-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
60795cb
commit 3a7b22c
Showing
4 changed files
with
259 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
<?php | ||
namespace Consolidation\Config; | ||
|
||
/** | ||
* Overlay different configuration objects that implement ConfigInterface | ||
* to make a priority-based, merged configuration object. | ||
* | ||
* Note that using a ConfigOverlay hides the defaults stored in each | ||
* individual configuration context. When using overlays, always call | ||
* getDefault / setDefault on the ConfigOverlay object itself. | ||
*/ | ||
class ConfigOverlay implements ConfigInterface | ||
{ | ||
protected $contexts = []; | ||
|
||
public function __construct() | ||
{ | ||
$this->contexts['default'] = new Config(); | ||
$this->contexts['process'] = new Config(); | ||
} | ||
|
||
/** | ||
* Add a named configuration object to the configuration overlay. | ||
* Configuration objects added LAST have HIGHEST priority, with the | ||
* exception of the fact that the process context always has the | ||
* highest priority. | ||
*/ | ||
public function addContext($name, ConfigInterface $config) | ||
{ | ||
$process = $this->contexts['process']; | ||
unset($this->contexts['process']); | ||
unset($this->contexts[$name]); | ||
$this->contexts[$name] = $config; | ||
$this->contexts['process'] = $process; | ||
} | ||
|
||
public function hasContext($name) | ||
{ | ||
return isset($this->contexts[$name]); | ||
} | ||
|
||
public function getContext($name) | ||
{ | ||
if ($this->hasContext($name)) { | ||
return $this->contexts[$name]; | ||
} | ||
return new Config(); | ||
} | ||
|
||
/** | ||
* Determine if a non-default config value exists. | ||
*/ | ||
public function findContext($key) | ||
{ | ||
foreach (array_reverse($this->contexts) as $name => $config) { | ||
if ($config->has($key)) { | ||
return $config; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
/** | ||
* @inheritdoc | ||
*/ | ||
public function has($key) | ||
{ | ||
return $this->findContext($key) != false; | ||
} | ||
|
||
/** | ||
* @inheritdoc | ||
*/ | ||
public function get($key, $default = null) | ||
{ | ||
$context = $this->findContext($key); | ||
if ($context) { | ||
return $context->get($key, $default); | ||
} | ||
return $default; | ||
} | ||
|
||
/** | ||
* @inheritdoc | ||
*/ | ||
public function set($key, $value) | ||
{ | ||
return $this->contexts['process']->set($key, $value); | ||
} | ||
|
||
/** | ||
* @inheritdoc | ||
*/ | ||
public function import($data) | ||
{ | ||
throw new \Exception('The method "import" is not supported for the ConfigOverlay class.'); | ||
} | ||
|
||
/** | ||
* @inheritdoc | ||
*/ | ||
public function export() | ||
{ | ||
$export = []; | ||
foreach ($this->contexts as $name => $config) { | ||
$export = array_merge_recursive($export, $config->export()); | ||
} | ||
return $export; | ||
} | ||
|
||
/** | ||
* @inheritdoc | ||
*/ | ||
public function hasDefault($key) | ||
{ | ||
return $this->contexts['default']->has($key); | ||
} | ||
|
||
/** | ||
* @inheritdoc | ||
*/ | ||
public function getDefault($key, $default = null) | ||
{ | ||
return $this->contexts['default']->get($key, $default); | ||
} | ||
|
||
/** | ||
* @inheritdoc | ||
*/ | ||
public function setDefault($key, $value) | ||
{ | ||
return $this->contexts['default']->set($key, $value); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
<?php | ||
namespace Consolidation\Config; | ||
|
||
use Consolidation\Config\Loader\ConfigProcessor; | ||
use Consolidation\Config\Loader\YamlConfigLoader; | ||
|
||
class ConfigOverlayTest extends \PHPUnit_Framework_TestCase | ||
{ | ||
protected $overlay; | ||
|
||
protected function setUp() | ||
{ | ||
$aliasContext = new Config(); | ||
$aliasContext->import([ | ||
'hidden-by-a' => 'alias hidden-by-a', | ||
'hidden-by-process' => 'alias hidden-by-process', | ||
'options' =>[ | ||
'a-a' => 'alias-a', | ||
], | ||
'command' => [ | ||
'foo' => [ | ||
'bar' => [ | ||
'command' => [ | ||
'options' => [ | ||
'a-b' => 'alias-b', | ||
], | ||
], | ||
], | ||
], | ||
], | ||
]); | ||
|
||
$configFileContext = new Config(); | ||
$configFileContext->import([ | ||
'hidden-by-cf' => 'config-file hidden-by-cf', | ||
'hidden-by-a' => 'config-file hidden-by-a', | ||
'hidden-by-process' => 'config-file hidden-by-process', | ||
'options' =>[ | ||
'cf-a' => 'config-file-a', | ||
], | ||
'command' => [ | ||
'foo' => [ | ||
'bar' => [ | ||
'command' => [ | ||
'options' => [ | ||
'cf-b' => 'config-file-b', | ||
], | ||
], | ||
], | ||
], | ||
], | ||
]); | ||
|
||
$this->overlay = new ConfigOverlay(); | ||
$this->overlay->set('hidden-by-process', 'process-h'); | ||
$this->overlay->addContext('cf', $configFileContext); | ||
$this->overlay->addContext('a', $aliasContext); | ||
$this->overlay->setDefault('df-a', 'default'); | ||
$this->overlay->setDefault('hidden-by-a', 'default hidden-by-a'); | ||
$this->overlay->setDefault('hidden-by-cf', 'default hidden-by-cf'); | ||
$this->overlay->setDefault('hidden-by-process', 'default hidden-by-process'); | ||
} | ||
|
||
public function testGetPriority() | ||
{ | ||
$this->assertEquals('process-h', $this->overlay->get('hidden-by-process')); | ||
$this->assertEquals('config-file hidden-by-cf', $this->overlay->get('hidden-by-cf')); | ||
$this->assertEquals('alias hidden-by-a', $this->overlay->get('hidden-by-a')); | ||
} | ||
|
||
public function testDefault() | ||
{ | ||
$this->assertEquals('alias-a', $this->overlay->get('options.a-a')); | ||
$this->assertEquals('alias-a', $this->overlay->get('options.a-a', 'ignored')); | ||
$this->assertEquals('default', $this->overlay->getDefault('df-a', 'ignored')); | ||
$this->assertEquals('nsv', $this->overlay->getDefault('a-a', 'nsv')); | ||
|
||
$this->overlay->setDefault('df-a', 'new value'); | ||
$this->assertEquals('new value', $this->overlay->getDefault('df-a', 'ignored')); | ||
} | ||
|
||
public function testExport() | ||
{ | ||
$data = $this->overlay->export(); | ||
|
||
$this->assertEquals('config-file-a', $data['options']['cf-a']); | ||
$this->assertEquals('alias-a', $data['options']['a-a']); | ||
} | ||
|
||
/** | ||
* @expectedException Exception | ||
*/ | ||
public function testImport() | ||
{ | ||
$data = $this->overlay->import(['a' => 'value']); | ||
} | ||
|
||
public function testChangePriority() | ||
{ | ||
// Get and re-add the 'cf' context. Now, it should have a higher | ||
// priority than the 'alias' context, but should still have a lower | ||
// priority than the 'process' context. | ||
$configFileContext = $this->overlay->getContext('cf'); | ||
$this->overlay->addContext('cf', $configFileContext); | ||
|
||
// These asserts are the same as in testGetPriority | ||
$this->assertEquals('process-h', $this->overlay->get('hidden-by-process')); | ||
$this->assertEquals('config-file hidden-by-cf', $this->overlay->get('hidden-by-cf')); | ||
|
||
// This one has changed: the config-file value is now found instead | ||
// of the alias value. | ||
$this->assertEquals('config-file hidden-by-a', $this->overlay->get('hidden-by-a')); | ||
} | ||
} |