Skip to content
This repository was archived by the owner on Oct 26, 2024. It is now read-only.

Commit 684e48d

Browse files
committed
Merge pull request #4 from maschmann/feature/import_and_default_values
Feature/import and default values
2 parents 2841c7d + 1fc4859 commit 684e48d

17 files changed

+413
-142
lines changed

CHANGELOG.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Changelog
2+
3+
## v2.0.0
4+
5+
* Dropping php 5.3 support
6+
* architectural changes
7+
8+
## v1.2.0
9+
10+
* improved overall code quality (scrutinizer suggestions)
11+
* improved code coverage
12+
* reworked __construct() behavior of Config classes
13+
14+
## v1.1.0
15+
16+
* Moved to PSR-4, closed extension points
17+
18+
## v1.0.0
19+
20+
* First stable draft release

Config/AbstractConfig.php

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
<?php
2+
/*
3+
* This file is part of the php-utilities package.
4+
*
5+
* (c) Marc Aschmann <[email protected]>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
namespace Asm\Config;
11+
12+
use Asm\Data\Data;
13+
use Symfony\Component\Yaml\Yaml;
14+
15+
/**
16+
* Class AbstractConfig
17+
*
18+
* @package Asm\Config
19+
* @author marc aschmann <[email protected]>
20+
* @codeCoverageIgnore
21+
* @uses Asm\Data\Data
22+
* @uses Symfony\Component\Yaml\Yaml
23+
*/
24+
abstract class AbstractConfig extends Data
25+
{
26+
/**
27+
* @var bool
28+
*/
29+
protected $filecheck = true;
30+
31+
/**
32+
* @var array
33+
*/
34+
protected $imports = [];
35+
36+
/**
37+
* @var array
38+
*/
39+
protected $default = [];
40+
41+
/**
42+
* Default constructor.
43+
*
44+
* @param array $param
45+
*/
46+
public function __construct(array $param)
47+
{
48+
if (isset($param['filecheck'])) {
49+
$this->filecheck = (bool)$param['filecheck'];
50+
}
51+
52+
$this->setConfig($param['file']);
53+
}
54+
55+
/**
56+
* Add named property to config object
57+
* and insert config as array.
58+
*
59+
* @param string $name name of property
60+
* @param string $file string $file absolute filepath/filename.ending
61+
*/
62+
public function addConfig($name, $file)
63+
{
64+
$this->set($name, $this->readConfig($file));
65+
}
66+
67+
/**
68+
* Read config file via YAML parser.
69+
*
70+
* @param string $file absolute filepath/filename.ending
71+
* @return array config array
72+
*/
73+
public function readConfig($file)
74+
{
75+
$config = $this->readFile($file);
76+
$config = $this->extractImports($config);
77+
$config = $this->extractDefault($config);
78+
$this->mergeDefault();
79+
80+
return array_replace_recursive(
81+
$this->default,
82+
$config
83+
);
84+
}
85+
86+
/**
87+
* Add config to data storage.
88+
*
89+
* @param string $file absolute filepath/filename.ending
90+
*/
91+
public function setConfig($file)
92+
{
93+
$this->setByArray(
94+
array_replace_recursive(
95+
$this->default,
96+
$this->readConfig($file)
97+
)
98+
);
99+
}
100+
101+
/**
102+
* Read yaml files.
103+
*
104+
* @param string $file path/filename
105+
* @return array
106+
*/
107+
private function readFile($file)
108+
{
109+
if ($this->filecheck && !is_file($file)) {
110+
throw new \InvalidArgumentException(
111+
'Config::Abstract() - Given config file ' . $file . ' does not exist!'
112+
);
113+
}
114+
115+
return (array)Yaml::parse($file);
116+
}
117+
118+
/**
119+
* get all import files from config, if set and remove node.
120+
*
121+
* @param array $config
122+
* @return array
123+
*/
124+
private function extractImports(array $config)
125+
{
126+
if (array_key_exists('imports', $config) && 0 < count($config['imports'])) {
127+
$this->imports = [];
128+
foreach ($config['imports'] as $key => $import) {
129+
if (false === empty($import['resource'])) {
130+
$this->imports = array_replace_recursive(
131+
$this->imports,
132+
$this->readFile($import['resource'])
133+
);
134+
}
135+
}
136+
137+
unset($config['imports']);
138+
}
139+
140+
return $config;
141+
}
142+
143+
/**
144+
* Get default values if set and remove node from config.
145+
*
146+
* @param array $config
147+
* @return array
148+
*/
149+
private function extractDefault($config)
150+
{
151+
if (array_key_exists('default', $config)) {
152+
$this->default = $config['default'];
153+
unset($config['default']);
154+
}
155+
156+
return $config;
157+
}
158+
159+
/**
160+
* Prepare the defaults and replace recursively.
161+
*/
162+
private function mergeDefault()
163+
{
164+
$this->default = array_replace_recursive($this->imports, $this->default);
165+
}
166+
}

Config/Config.php

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,6 @@
1717
*/
1818
final class Config
1919
{
20-
/**
21-
* @var array
22-
*/
23-
private static $whitelist = [
24-
'ConfigDefault',
25-
'ConfigEnv',
26-
'ConfigTimer',
27-
];
28-
2920
/**
3021
* Get object of specific class.
3122
*
@@ -37,11 +28,11 @@ final class Config
3728
*/
3829
public static function factory(array $param, $class = 'ConfigDefault')
3930
{
40-
if (in_array($class, self::$whitelist)) {
41-
if (false === strpos($class, 'Asm')) {
42-
$class = __NAMESPACE__ . '\\' . $class;
43-
}
31+
if (false === strpos($class, 'Asm')) {
32+
$class = __NAMESPACE__ . '\\' . $class;
33+
}
4434

35+
if (class_exists($class)) {
4536
// allow config names without ending
4637
if (empty($param['file'])) {
4738
throw new \InvalidArgumentException('Config::factory() - config filename missing in param array!');

Config/ConfigAbstract.php

Lines changed: 0 additions & 83 deletions
This file was deleted.

Config/ConfigDefault.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@
1515
* @package Asm\Config
1616
* @author marc aschmann <[email protected]>
1717
*/
18-
final class ConfigDefault extends ConfigAbstract implements ConfigInterface
18+
final class ConfigDefault extends AbstractConfig implements ConfigInterface
1919
{
2020
}

Config/ConfigEnv.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
* @package Asm\Config
1818
* @author marc aschmann <[email protected]>
1919
*/
20-
final class ConfigEnv extends ConfigAbstract implements ConfigInterface
20+
final class ConfigEnv extends AbstractConfig implements ConfigInterface
2121
{
2222
/**
2323
* @var string
@@ -66,6 +66,11 @@ private function mergeEnvironments($param)
6666
$merged = $config->get($this->defaultEnv);
6767
}
6868

69-
$this->setByArray($merged);
69+
$this->setByArray(
70+
array_replace_recursive(
71+
$this->default,
72+
$merged
73+
)
74+
);
7075
}
7176
}

Config/ConfigTimer.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* @package Asm\Config
1616
* @author marc aschmann <[email protected]>
1717
*/
18-
final class ConfigTimer extends ConfigAbstract implements ConfigInterface
18+
final class ConfigTimer extends AbstractConfig implements ConfigInterface
1919
{
2020
/**
2121
* Convert config date strings to \DateTime objects or \DateIntervals.

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,16 @@ Available types are:
2828
* ConfigEnv - provides the possibility to get an environment-merged config. Based on the currently provided env, you'll have e.g. prod -> dev merged, with prod node as a master.
2929
* ConfigTimer is a specialised for of config to provide pre-generated DateTime objects for the Timer class.
3030

31+
Configs now also support the "imports" syntax from symfony configs.
32+
33+
```
34+
imports:
35+
- { resource: defaults.yml }
36+
```
37+
There is the possibility to use a "default" node in all configs, except timers, which will be used as merge-base.
38+
Imported configs will be treated just like the "default" node and also become the base for merging.
39+
The order of merges is import -> default -> prod -> $env.
40+
3141
### Timer
3242
Provides functionality to check if there's a current holiday, has configurable "timers" to check uf e.g. your hotline should be available etc.
3343
Extensive examples can be found within both, the TestData and UnitTests :-)

0 commit comments

Comments
 (0)