1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* @package: chapi |
4
|
|
|
* |
5
|
|
|
* @author: msiebeneicher |
6
|
|
|
* @since: 2017-03-22 |
7
|
|
|
* |
8
|
|
|
*/ |
9
|
|
|
|
10
|
|
|
namespace Chapi\Component\Config; |
11
|
|
|
|
12
|
|
|
use Symfony\Component\Yaml\Parser as YamlParser; |
13
|
|
|
|
14
|
|
|
class ChapiConfig implements ChapiConfigInterface |
15
|
|
|
{ |
16
|
|
|
/** |
17
|
|
|
* @var string[] |
18
|
|
|
*/ |
19
|
|
|
private $directoryPaths = []; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* @var YamlParser |
23
|
|
|
*/ |
24
|
|
|
private $parser; |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* @var string |
28
|
|
|
*/ |
29
|
|
|
private $activeProfile = ''; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* @var array |
33
|
|
|
*/ |
34
|
|
|
private $config = null; |
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* ChapiConfig constructor. |
38
|
|
|
* @param string[] $directoryPaths |
39
|
|
|
* @param YamlParser $parser |
40
|
|
|
* @param string $activeProfile |
41
|
|
|
*/ |
42
|
3 |
|
public function __construct( |
43
|
|
|
$directoryPaths, |
44
|
|
|
YamlParser $parser, |
45
|
|
|
$activeProfile |
46
|
|
|
) { |
47
|
3 |
|
$this->directoryPaths = $directoryPaths; |
48
|
3 |
|
$this->parser = $parser; |
49
|
3 |
|
$this->activeProfile = $activeProfile; |
50
|
3 |
|
} |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* @inheritdoc |
54
|
|
|
*/ |
55
|
2 |
|
public function getProfileConfig() |
56
|
|
|
{ |
57
|
2 |
|
$config = $this->getConfig(); |
58
|
2 |
|
return $config['profiles'][$this->activeProfile]; |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* @inheritdoc |
63
|
|
|
*/ |
64
|
3 |
|
public function getConfig() |
65
|
|
|
{ |
66
|
3 |
|
if (is_null($this->config)) { |
67
|
3 |
|
$this->config = $this->loadConfigs(); |
68
|
|
|
} |
69
|
|
|
|
70
|
3 |
|
return $this->config; |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
/** |
74
|
|
|
* @return array |
75
|
|
|
*/ |
76
|
3 |
|
private function loadConfigs() |
77
|
|
|
{ |
78
|
3 |
|
$config = []; |
79
|
|
|
|
80
|
3 |
|
foreach ($this->directoryPaths as $directoryPath) { |
81
|
3 |
|
if (!is_dir($directoryPath)) { |
82
|
|
|
throw new \InvalidArgumentException(sprintf('Path "%s" is not valid', $directoryPath)); |
83
|
|
|
} |
84
|
|
|
|
85
|
3 |
|
$configPart = $this->loadConfig($directoryPath); |
86
|
3 |
|
$config = self::arrayMergeRecursiveDistinct($config, $configPart); |
87
|
|
|
} |
88
|
|
|
|
89
|
3 |
|
return $config; |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
/** |
93
|
|
|
* @param string $path |
94
|
|
|
* @return array |
|
|
|
|
95
|
|
|
*/ |
96
|
3 |
|
private function loadConfig($path) |
97
|
|
|
{ |
98
|
3 |
|
$filePath = $path . DIRECTORY_SEPARATOR . self::CONFIG_FILE_NAME; |
99
|
|
|
|
100
|
3 |
|
if (is_file($filePath)) { |
101
|
3 |
|
$config = $this->parser->parse( |
102
|
|
|
file_get_contents($filePath) |
103
|
|
|
); |
104
|
|
|
|
105
|
3 |
|
return $config; |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
return []; |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
/** |
112
|
|
|
* array_merge_recursive does indeed merge arrays, but it converts values with duplicate |
113
|
|
|
* keys to arrays rather than overwriting the value in the first array with the duplicate |
114
|
|
|
* value in the second array, as array_merge does. I.e., with array_merge_recursive, |
115
|
|
|
* this happens (documented behavior): |
116
|
|
|
* |
117
|
|
|
* array_merge_recursive(array('key' => 'org value'), array('key' => 'new value')); |
118
|
|
|
* => array('key' => array('org value', 'new value')); |
119
|
|
|
* |
120
|
|
|
* array_merge_recursive_distinct does not change the datatypes of the values in the arrays. |
121
|
|
|
* Matching keys' values in the second array overwrite those in the first array, as is the |
122
|
|
|
* case with array_merge, i.e.: |
123
|
|
|
* |
124
|
|
|
* array_merge_recursive_distinct(array('key' => 'org value'), array('key' => 'new value')); |
125
|
|
|
* => array('key' => array('new value')); |
126
|
|
|
* |
127
|
|
|
* Parameters are passed by reference, though only for performance reasons. They're not |
128
|
|
|
* altered by this function. |
129
|
|
|
* |
130
|
|
|
* @param array $array1 |
131
|
|
|
* @param array $array2 |
132
|
|
|
* @return array |
133
|
|
|
* @author Daniel <daniel (at) danielsmedegaardbuus (dot) dk> |
134
|
|
|
* @author Gabriel Sobrinho <gabriel (dot) sobrinho (at) gmail (dot) com> |
135
|
|
|
* |
136
|
|
|
* @see http://php.net/manual/de/function.array-merge-recursive.php |
137
|
|
|
*/ |
138
|
3 |
|
private static function arrayMergeRecursiveDistinct(array &$array1, array &$array2) |
139
|
|
|
{ |
140
|
3 |
|
$merged = $array1; |
141
|
|
|
|
142
|
3 |
|
foreach ($array2 as $key => &$value) { |
143
|
3 |
|
if (is_array($value) && isset($merged[$key]) && is_array($merged[$key])) { |
144
|
1 |
|
$merged[$key] = self::arrayMergeRecursiveDistinct($merged[$key], $value); |
145
|
|
|
} else { |
146
|
|
|
// add new element for numeric arrays |
147
|
3 |
|
if (isset($merged[$key]) && is_numeric($key)) { |
148
|
1 |
|
$merged[] = $value; |
149
|
|
|
} else { |
150
|
3 |
|
$merged[$key] = $value; |
151
|
|
|
} |
152
|
|
|
} |
153
|
|
|
} |
154
|
|
|
|
155
|
3 |
|
return $merged; |
156
|
|
|
} |
157
|
|
|
} |
158
|
|
|
|
This check compares the return type specified in the
@return
annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.If the return type contains the type array, this check recommends the use of a more specific type like
String[]
orarray<String>
.