Skip to content

Commit

Permalink
add cascading defaults
Browse files Browse the repository at this point in the history
  • Loading branch information
electricjones committed Sep 4, 2015
1 parent 54fc386 commit f996f74
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 3 deletions.
7 changes: 5 additions & 2 deletions CHANGELOG.md
@@ -1,10 +1,13 @@
# Changelog
All Notable changes to `Manager` will be documented in this file

# NEXT
# Future
- Initialize `CollectsItemsTrait` and `Collection` class
- Initialize `IocContainerTrait` for basic DI functionality

#v0.8.5 - NEXT
- Adds `IocContainerTrait` for basic DI functionality
- Adds `loadDefaults(array $defaults)` to `ManagesItemsTrait`

#v0.8.4 - 2015-7-14
- Better documentation (README.md)
- Add protected items functionality
Expand Down
45 changes: 45 additions & 0 deletions README.md
Expand Up @@ -92,6 +92,51 @@ $manager->protect('some.data'); //now some.data and everything under it cannot b
$manager->set('some.data.here', 'new-value'); // throws an exception
```

## Merging Defaults Into Current Dataset
When using Manager to store configuration data, it is important to be able to set defaults.
You can merge an array of defaults into manager via `loadDefaults(array $defaults)`

Imagine your configuration starts like
```php
$manager = new Manager([
'name' => 'My Awesome App',
'site' => [
'url' => 'http://youwishyouwerethiscool.com/',
'assets' => '/static'
]
]);
```

But your app needs `site.title` and `author`. Simply
```php
$manager->loadDefaults([
'site' => [
'url' => 'http://the_default_url.com/',
'protocol' => "https",
'assets' => '/assets',
],
'database' => "mysql"
]);
```

And now, your configuration looks like
```php
'name' => 'My Awesome App',
'site' => [
'url' => 'http://youwishyouwerethiscool.com/'
'protocol' => "https",
'assets' => '/static' // NOT the default /assets
],
'database' => "mysql"
```

A couple of things to keep in mind:
* This works recursively and as far down as you want.
* If any value is set before loading defaults, that value is preserved
* If a starting value is set to an array (`one.two = []`) and a default lives beneath (`one.two.three = default`), then the default **will** be set.
* On the other hand, if the value exists and is **not** an array, the default will be ignored.
(`one.two = 'something'`) In this case, there is no `one.two.three`, even after loading defaults.

## Using Manager Traits
If you have your own container objects and want to add Manager functionality to them, you may import traits into your class.

Expand Down
3 changes: 2 additions & 1 deletion composer.json
Expand Up @@ -4,7 +4,8 @@
"keywords": [
"data", "collection", "container", "manager",
"nest", "nested", "array", "dot notation",
"access", "deep data"
"access", "deep data", "config", "configuration",
"defaults"
],
"homepage": "https://github.com/chrismichaels84/data-manager",
"license": "MIT",
Expand Down
24 changes: 24 additions & 0 deletions src/Traits/ManagesItemsTrait.php
@@ -1,6 +1,7 @@
<?php
namespace Michaels\Manager\Traits;

use Interop\Container\Exception\NotFoundException;
use Michaels\Manager\Contracts\ManagesItemsInterface;
use Michaels\Manager\Exceptions\ItemNotFoundException;
use Michaels\Manager\Exceptions\ModifyingProtectedValueException;
Expand Down Expand Up @@ -273,6 +274,29 @@ public function protect($item)
return $this;
}

public function loadDefaults(array $defaults)
{
$this->mergeDefaults($defaults);
}

protected function mergeDefaults(array $defaults, $level = '')
{
foreach ($defaults as $key => $value) {
if (is_array($value)) {
$original = $this->getIfExists(ltrim("$level.$key", "."));
if (is_array($original)) {
$this->mergeDefaults($value, "$level.$key");
} elseif ($original instanceof NoItemFoundMessage) {
$this->set(ltrim("$level.$key", "."), $value);
}
} else {
if (!$this->exists(ltrim("$level.$key", "."))) {
$this->set(ltrim("$level.$key", "."), $value);
}
}
}
}

/**
* Get the collection of items as JSON.
*
Expand Down
76 changes: 76 additions & 0 deletions tests/Traits/ManagesItemsTest.php
Expand Up @@ -393,4 +393,80 @@ public function testProtectItemsUnderANest()
$manager->protect('some');
$manager->set('some.data.here', 'new-value');
}

public function testLoadDefaultsIntoEmptyManager()
{
$manager = new Manager();

$defaults = [
'one' => [
'two' => [
'three' => [
'true' => true,
]
],
'four' => 'four'
]
];

$manager->loadDefaults($defaults);

$this->assertEquals($defaults, $manager->getAll(), "failed to load defaults");
}

public function testLoadDefaultsIntoNonEmptyManager()
{
$defaults = [
'one' => [
'two' => [
'three' => [
'true' => true,
]
],
'four' => [
'six' => false,
]
],
'five' => 5,
'seven' => [
'a' => 'A',
'b' => 'B',
'c' => 'C',
]
];

$starting = [
'one' => [
'two' => [],
'four' => 'michael'
],
'seven' => [
'c' => 'over-ridden-c',
],
'eight' => 8,
];

$expected = [
'one' => [
'two' => [
'three' => [
'true' => true,
]
],
'four' => 'michael',
],
'five' => 5,
'seven' => [
'a' => 'A',
'b' => 'B',
'c' => 'over-ridden-c',
],
'eight' => 8,
];

$manager = new Manager($starting);
$manager->loadDefaults($defaults);

$this->assertEquals($expected, $manager->getAll(), "failed to load defaults");
}
}

0 comments on commit f996f74

Please sign in to comment.