Last active
December 23, 2015 05:09
-
-
Save iwyg/6585278 to your computer and use it in GitHub Desktop.
dot notation aware config class
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
<?php | |
/** | |
* This File is part of the Acme\Configuration package | |
* | |
* (c) Thomas Appel <[email protected]> | |
* | |
* For full copyright and license information, please refer to the LICENSE file | |
* that was distributed with this package. | |
*/ | |
namespace Acme\Configuration; | |
/** | |
* @class Config | |
* @package Acme\Configuration | |
* @version $Id$ | |
*/ | |
class Config | |
{ | |
/** | |
* config | |
* | |
* @var array | |
*/ | |
private $config; | |
/** | |
* reference pointer to config values | |
* | |
* @var array | |
*/ | |
private $reference; | |
/** | |
* @param array $config | |
* | |
* @access public | |
*/ | |
public function __construct(array $config = []) | |
{ | |
$this->reference = []; | |
$this->config = $config; | |
} | |
/** | |
* get a config item | |
* | |
* @param mixed $key | |
* @param mixed $default | |
* | |
* @access public | |
* @return mixed | |
*/ | |
public function get($key, $default = null) | |
{ | |
if ($result = $this->doGet($this->config, $key, '.', $key, explode('.', $key))) { | |
return $result; | |
} | |
return $default; | |
} | |
/** | |
* set a congig value | |
* | |
* @param mixed $param | |
* @param mixed $value | |
* | |
* @access public | |
* @return void | |
*/ | |
public function set($key, $value) | |
{ | |
return $this->configSet($key, $value, $this->config); | |
} | |
/** | |
* configSet | |
* | |
* @param string $query | |
* @param mixed $value | |
* @param array $input | |
* @param string $separator | |
* | |
* @access private | |
* @return mixed | |
*/ | |
private function configSet($query, $value, array &$input = [], $separator = '.') | |
{ | |
$keys = explode($separator, $query); | |
$pointer = &$input; | |
while (count($keys) > 0) { | |
$pointer = is_array($pointer) ? $pointer : []; | |
$pointer[$key = array_shift($keys)] = isset($pointer[$key]) ? $pointer[$key] : []; | |
$pointer = &$pointer[$key]; | |
} | |
$pointer = $value; | |
$this->reference[$query] = $value; | |
} | |
/** | |
* doGet | |
* | |
* @param mixed $array | |
* @param mixed $query | |
* @param string $separator | |
* @param mixed $originalQ | |
* @param array $keys | |
* | |
* @access protected | |
* @return mixed | |
*/ | |
protected function doGet(&$array = [], $query = null, $separator = '.', $originalQ = null, array $keys = []) | |
{ | |
// if the query is already parsed return immediately | |
if ($result = $this->getReference($originalQ)) { | |
return $result; | |
} | |
return $this->configGet($array, $query, $separator, $originalQ, $keys, $result); | |
} | |
/** | |
* configGet | |
* | |
* @param mixed $array | |
* @param string $query | |
* @param string $separator | |
* @param string $originalQ | |
* | |
* @access private | |
* @return mixed | |
*/ | |
private function configGet(&$array = [], $query = null, $separator = '.', $originalQ = null, array $keys = [], $result = null) | |
{ | |
$key = array_shift($keys); | |
// we set both queries as pointer to the input array for faster | |
// retrieval | |
if (isset($array[$key])) { | |
if (is_array($result = $array[$key]) and ($count = count($keys)) > 0) { | |
if (1 === $count) { | |
$this->reference[substr($originalQ, -strrpos($originalQ, $separator))] =& $array[$key]; | |
} | |
return $this->doGet($array[$key], implode($separator, $keys), $separator, $originalQ, $keys); | |
} else { | |
$this->reference[$originalQ] =& $array[$key]; | |
return $this->reference[$originalQ]; | |
} | |
} | |
return $result; | |
} | |
/** | |
* getReference | |
* | |
* @param mixed $query | |
* | |
* @access private | |
* @return mixed | |
*/ | |
private function getReference($query) | |
{ | |
if (isset($this->reference[$query])) { | |
return $this->reference[$query]; | |
} | |
return false; | |
} | |
} |
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
<?php | |
/** | |
* This File is part of the Acme\Configuration\Tests package | |
* | |
* (c) Thomas Appel <[email protected]> | |
* | |
* For full copyright and license information, please refer to the LICENSE file | |
* that was distributed with this package. | |
*/ | |
namespace Acme\Configuration\Tests; | |
use Acme\Configuration\Config; | |
class ConfigTest extends \PHPUnit_Framework_TestCase | |
{ | |
/** | |
* @test | |
*/ | |
public function testConfigGet() | |
{ | |
$config = new Config($data = $this->getConfigData()); | |
$this->assertEquals('baz', $config->get('foo.bar')); | |
$this->assertEquals(['bar' => 'baz'], $config->get('foo')); | |
$this->assertEquals('some value', $config->get('zoom.somestuff')); | |
$this->assertEquals(['somestuff' => 'some value'], $config->get('zoom')); | |
$this->assertEquals('nested', $config->get('deep.deep.deep.deep.deep')); | |
} | |
/** | |
* @test | |
*/ | |
public function testConfigGetShouldReturnNull() | |
{ | |
$config = new Config($data = $this->getConfigData()); | |
$this->assertNull($config->get('bar')); | |
$this->assertNull($config->get('bar.bam')); | |
} | |
/** | |
* @test | |
*/ | |
public function testConfigGetShouldReturnDefault() | |
{ | |
$config = new Config($data = $this->getConfigData()); | |
$this->assertSame('baz', $config->get('bar', 'baz')); | |
$this->assertSame('baz', $config->get('bar.bam', 'baz')); | |
} | |
/** | |
* @test | |
*/ | |
public function testConfigSet() | |
{ | |
$config = new Config(); | |
$config->set('foo.bar', 'baz'); | |
$this->assertEquals(['bar' => 'baz'], $config->get('foo')); | |
$this->assertEquals('baz', $config->get('foo.bar')); | |
} | |
/** | |
* @test | |
*/ | |
public function testConfigSetOverride() | |
{ | |
$config = new Config(); | |
$config->set('foo.bar', 'baz'); | |
$this->assertEquals(['bar' => 'baz'], $config->get('foo')); | |
$this->assertEquals('baz', $config->get('foo.bar')); | |
$config->set('foo.bar.foo.bar.foo.bar', 'done'); | |
$this->assertSame('done', $config->get('foo.bar.foo.bar.foo.bar'), 'foo.bar nested should be done'); | |
$this->assertSame(['bar' => 'done'], $config->get('foo.bar.foo.bar.foo')); | |
$config->set('deep.deep', 'nested'); | |
$this->assertEquals(['deep' => 'nested'], $config->get('deep')); | |
$this->assertEquals('nested', $config->get('deep.deep')); | |
$config->set('deep.deep.deep.deep.deep', 'nested'); | |
$this->assertEquals('nested', $config->get('deep.deep.deep.deep.deep')); | |
$this->assertEquals(['deep' => 'nested'], $config->get('deep.deep.deep.deep')); | |
} | |
/** | |
* @test | |
*/ | |
public function testConfigSetOverrideDefault() | |
{ | |
$config = new Config($data = $this->getConfigData()); | |
$this->assertEquals('nested', $config->get('deep.deep.deep.deep.deep')); | |
$config->set('deep.deep', 'new value'); | |
$this->assertEquals('new value', $config->get('deep.deep')); | |
} | |
/** | |
* testConfigGetFromReference | |
* | |
* @access public | |
* @return mixed | |
*/ | |
public function testConfigGetFromReference() | |
{ | |
$config = $this->getMock('Acme\Configuration\Config', ['configGet']); | |
$config->expects($this->never())->method('configGet'); | |
$config->set('foo.bar', ['baz' => 'some value']); | |
$config->set('foo.bar.baz', 'some value'); | |
$this->assertEquals('some value', $config->get('foo.bar.baz')); | |
$this->assertEquals(['baz' => 'some value'], $config->get('foo.bar')); | |
} | |
protected function getConfigData() | |
{ | |
return [ | |
'foo' => [ | |
'bar' => 'baz' | |
], | |
'zoom' => [ | |
'somestuff' => 'some value' | |
], | |
'deep' => [ | |
'deep' => [ | |
'deep' => [ | |
'deep' => [ | |
'deep' => 'nested' | |
] | |
] | |
] | |
] | |
]; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment