Skip to content

Commit

Permalink
Added getSubConfig() functionality.
Browse files Browse the repository at this point in the history
  • Loading branch information
schlessera committed Feb 17, 2016
1 parent 3415df5 commit c8a3a36
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 26 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Expand Up @@ -2,6 +2,11 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

## [0.1.13] - 2016-02-17
### Added
- Added `getSubConfig()` to extract the subtree at a specific level & key.
- Added corresponding tests.

## [0.1.12] - 2016-02-17
### Fixed
- Updated `brightnucleus/exceptions` dependency.
Expand Down Expand Up @@ -76,6 +81,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
### Added
- Initial release to GitHub.

[0.1.13]: https://github.com/brightnucleus/config/compare/v0.1.12...v0.1.13
[0.1.12]: https://github.com/brightnucleus/config/compare/v0.1.11...v0.1.12
[0.1.11]: https://github.com/brightnucleus/config/compare/v0.1.10...v0.1.11
[0.1.10]: https://github.com/brightnucleus/config/compare/v0.1.9...v0.1.10
Expand Down
36 changes: 26 additions & 10 deletions README.md
Expand Up @@ -64,24 +64,20 @@ class Example {
/**
* Instantiate an Example object.
*
* @param ConfigInterface $config Config to parametrize the object.
* @param string|null $config_key Optional. Config key that represents the
* subtree for this class.
* @throws RuntimeException If the Config could not be parsed correctly.
* @param ConfigInterface $config Config to parametrize the object.
* @throws RuntimeException If the Config could not be parsed correctly.
*/
public function __construct( ConfigInterface $config, $config_key = null ) {
$this->processConfig( $config, $config_key ?: 'BrightNucleus\Example' );
public function __construct( ConfigInterface $config ) {
$this->processConfig( $config );
}

/**
* Do something.
*/
public function run() {
$key = 'test_key;';
$key = 'test_key';

// Outputs:
// The value of the config key "test_key" is "test_value".
printf(
return sprintf(
_( 'The value of the config key "$1%s" is "$2%s".'),
$key,
$this->getConfigKey( $key )
Expand All @@ -90,6 +86,26 @@ class Example {
}
```

### Example of how to put the configuration into the class

You can combine all of your configurations into 1 single file and only pass "Sub-Configurations" to the individual components. This way, you can save a file access and a complete validation pass for each component.

Here's how you can pass the configuration file into the class:

```PHP
<?php namespace BrightNucleus\Example;

function init() {
$configFile = __DIR__ . '/config/example_settings.php';
$config = new Config( include( $configFile ) );
$example = new Example( $config->getSubConfig( 'BrightNucleus\Example' ) );

// Outputs:
// The value of the config key "test_key" is "test_value".
echo $example->run();
}
```

See [link to post coming soon] for more details.

## Contributing
Expand Down
73 changes: 61 additions & 12 deletions src/AbstractConfig.php
Expand Up @@ -72,17 +72,7 @@ public function __construct(array $config, $delimiter = null)
*/
public function getKey()
{
$keys = $this->getKeyArguments(func_get_args());
Assert\that($keys)->all()->string()->notEmpty();

if (! $this->hasKey($keys)) {
throw new OutOfRangeException(
sprintf(
_('The configuration key %1$s does not exist.'),
implode('->', $keys)
)
);
}
$keys = $this->validateKeys(func_get_args());

$keys = array_reverse($keys);
$array = $this->getArrayCopy();
Expand All @@ -109,7 +99,6 @@ public function hasKey()
{
try {
$keys = array_reverse($this->getKeyArguments(func_get_args()));
Assert\thatAll($keys)->string()->notEmpty();

$array = $this->getArrayCopy();
while (count($keys) > 0) {
Expand Down Expand Up @@ -149,6 +138,66 @@ public function getKeys()
return array_keys((array)$this);
}

/**
* Get a new config at a specific sub-level.
*
* @since 0.1.13
*
* @param string ... List of keys.
* @return ConfigInterface
* @throws BadMethodCallException If no argument was provided.
* @throws OutOfRangeException If an unknown key is requested.
*/
public function getSubConfig()
{
$keys = $this->validateKeys(func_get_args());

$subConfig = clone $this;
$subConfig->reduceToSubKey($keys);

return $subConfig;
}

/**
* Validate a set of keys to make sure they exist.
*
* @since 0.1.13
*
* @param string ... List of keys.
* @return array List of keys.
* @throws BadMethodCallException If no argument was provided.
* @throws OutOfRangeException If an unknown key is requested.
*/
public function validateKeys()
{
$keys = $this->getKeyArguments(func_get_args());

Assert\that($keys)->all()->string()->notEmpty();

if (! $this->hasKey($keys)) {
throw new OutOfRangeException(
sprintf(
_('The configuration key %1$s does not exist.'),
implode('->', $keys)
)
);
}

return $keys;
}

/**
* Reduce the currently stored config array to a subarray at a specific level.
*
* @since 0.1.13
*
* @param array $keys Array of keys that point to a key down in the hierarchy.
*/
protected function reduceToSubkey(array $keys)
{
$this->exchangeArray($this->getKey($keys));
}

/**
* Recursively extract the configuration key arguments from an arbitrary array.
*
Expand Down
11 changes: 10 additions & 1 deletion src/ConfigInterface.php
Expand Up @@ -62,7 +62,6 @@ public function hasKey();
* @since 0.1.4 Accepts list of keys.
*
* @param string ... List of keys.
*
* @return mixed
*/
public function getKey();
Expand Down Expand Up @@ -93,4 +92,14 @@ public function getKeys();
* @return boolean
*/
public function isValid();

/**
* Get a new config at a specific sub-level.
*
* @since 0.1.13
*
* @param string ... List of keys.
* @return ConfigInterface
*/
public function getSubConfig();
}
3 changes: 1 addition & 2 deletions src/ConfigTrait.php
Expand Up @@ -42,8 +42,7 @@ protected function processConfig(ConfigInterface $config)
try {
$keys = func_get_args();
array_shift($keys);
Assert\that($keys)->all()->string()->notEmpty();
$config = new Config($config->getKey($keys));
$config = $config->getSubConfig($keys);
} catch (Exception $exception) {
throw new RuntimeException(
sprintf(
Expand Down
35 changes: 34 additions & 1 deletion tests/ConfigTest.php
Expand Up @@ -30,7 +30,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
* Don't use an array const to avoid bumping PHP requirement to 5.6.
*/
protected static $test_array = [
'random_string' => 'test_value',
'random_string' => 'test_value',
'positive_integer' => 42,
'negative_integer' => -256,
'positive_boolean' => true,
Expand Down Expand Up @@ -354,4 +354,37 @@ public function testConfigFileWithDefaults()
);
$this->assertFalse($config->getKey('some_other_key'));
}

public function testGetSubConfig()
{
$config = new Config(__DIR__ . '/fixtures/deep_config_file.php');
$subconfig = $config->getSubConfig('vendor/package');
$subsection1 = $config->getSubConfig('vendor', 'package', 'section_1');
$subsection2 = $subconfig->getSubConfig('section_2');
$this->assertInstanceOf('\BrightNucleus\Config\ConfigInterface', $config);
$this->assertInstanceOf('\BrightNucleus\Config\AbstractConfig', $config);
$this->assertInstanceOf('\BrightNucleus\Config\Config', $config);
$this->assertInstanceOf('\BrightNucleus\Config\ConfigInterface', $subconfig);
$this->assertInstanceOf('\BrightNucleus\Config\AbstractConfig', $subconfig);
$this->assertInstanceOf('\BrightNucleus\Config\Config', $subconfig);
$this->assertInstanceOf('\BrightNucleus\Config\ConfigInterface', $subsection1);
$this->assertInstanceOf('\BrightNucleus\Config\AbstractConfig', $subsection1);
$this->assertInstanceOf('\BrightNucleus\Config\Config', $subsection1);
$this->assertInstanceOf('\BrightNucleus\Config\ConfigInterface', $subsection2);
$this->assertInstanceOf('\BrightNucleus\Config\AbstractConfig', $subsection2);
$this->assertInstanceOf('\BrightNucleus\Config\Config', $subsection2);
$this->assertTrue($config->hasKey('vendor/package'));
$this->assertTrue($config->hasKey('vendor/package/section_1/test_key_1'));
$this->assertTrue($config->hasKey('vendor/package/section_2/test_key_2'));
$this->assertTrue($subconfig->hasKey('section_1/test_key_1'));
$this->assertTrue($subconfig->hasKey('section_2/test_key_2'));
$this->assertTrue($subsection1->hasKey('test_key_1'));
$this->assertTrue($subsection2->hasKey('test_key_2'));
$this->setExpectedException(
'BrightNucleus\Exception\OutOfRangeException',
'The configuration key some_other_key does not exist.'
);
$this->assertFalse($config->getSubConfig('some_other_key'));

}
}
23 changes: 23 additions & 0 deletions tests/fixtures/deep_config_file.php
@@ -0,0 +1,23 @@
<?php
/**
* Config file with deeply nested test data for the unit tests.
*
* @package BrightNucleus\Config
* @author Alain Schlesser <alain.schlesser@gmail.com>
* @license GPL-2.0+
* @link http://www.brightnucleus.com/
* @copyright 2016 Alain Schlesser, Bright Nucleus
*/

namespace BrightNucleus\Config;

$test_data = [
'section_1' => [
'test_key_1' => 'test_value_1',
],
'section_2' => [
'test_key_2' => 'test_value_2',
],
];

return ['vendor' => ['package' => $test_data]];

0 comments on commit c8a3a36

Please sign in to comment.