Passed
Branch master (e773b5)
by Raffael
03:37
created

Config::mergeServiceConfig()   B

Complexity

Conditions 5
Paths 7

Size

Total Lines 18
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 9
nc 7
nop 3
dl 0
loc 18
rs 8.8571
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * Micro
7
 *
8
 * @copyright   Copryright (c) 2015-2018 gyselroth GmbH (https://gyselroth.com)
9
 * @license     MIT https://opensource.org/licenses/MIT
10
 */
11
12
namespace Micro\Container;
13
14
class Config
15
{
16
    /**
17
     * Config.
18
     *
19
     * @var iterable
20
     */
21
    protected $config = [];
22
23
    /**
24
     * Compiled config.
25
     *
26
     * @var array
27
     */
28
    protected $compiled = [];
29
30
    /**
31
     * Create container.
32
     *
33
     * @param iterable $config
34
     */
35
    public function __construct(Iterable $config = [])
36
    {
37
        $this->config = $config;
38
    }
39
40
    /**
41
     * Check if service is known to container config.
42
     *
43
     * @param string $name
44
     *
45
     * @return bool
46
     */
47
    public function has(string $name): bool
48
    {
49
        return isset($this->config[$name]);
50
    }
51
52
    /**
53
     * Get service configuration.
54
     *
55
     * @param string $name
56
     *
57
     * @return array
58
     */
59
    public function get(string $name): array
60
    {
61
        if (isset($this->compiled[$name])) {
62
            $config = $this->compiled[$name];
63
        } else {
64
            $this->compiled[$name] = $this->createServiceConfig($name);
65
            $config = $this->compiled[$name];
66
        }
67
68
        if (!isset($config['use'])) {
69
            $config['use'] = $name;
70
        }
71
72
        return $config;
73
    }
74
75
    /**
76
     * Parse env param.
77
     *
78
     * @param string $param
79
     *
80
     * @return string
81
     */
82
    public function getEnv(string $param): string
83
    {
84
        if (preg_match_all('#\{ENV\(([A-Za-z0-9_]+)(?:(,?)([^}]*))\)\}#', $param, $matches)) {
85
            if (4 !== count($matches)) {
86
                return $param;
87
            }
88
89
            for ($i = 0; $i < 1; ++$i) {
90
                $param = $this->parseEnv($param, $matches, $i);
91
            }
92
93
            return $param;
94
        }
95
96
        return $param;
97
    }
98
99
    /**
100
     * Parse env.
101
     *
102
     * @param string $param
103
     * @param array  $variables
104
     * @param int    $key
105
     *
106
     * @return string
107
     */
108
    protected function parseEnv(string $param, array $variables, int $key): string
109
    {
110
        $env = getenv($variables[1][$key]);
111
        if (false === $env && !empty($variables[3][$key])) {
112
            return str_replace($variables[0][$key], $variables[3][$key], $param);
113
        }
114
        if (false === $env) {
115
            throw new Exception\EnvVariableNotFound('env variable '.$variables[1][$key].' required but it is neither set not a default value exists');
116
        }
117
118
        return str_replace($variables[0][$key], $env, $param);
119
    }
120
121
    /**
122
     * Create service config.
123
     *
124
     * @param string $name
125
     *
126
     * @return array
127
     */
128
    protected function createServiceConfig(string $name): array
129
    {
130
        $config = [];
131
        if ($this->has($name)) {
132
            $config = $this->config[$name];
133
        }
134
135
        $class = $name;
136
        if (isset($config['use'])) {
137
            if (!is_string($config['use'])) {
138
                throw new Exception\InvalidConfiguration('use must be a string for service '.$name);
139
            }
140
141
            $class = $config['use'];
142
        }
143
144
        if (preg_match('#^\{(.*)\}$#', $class)) {
145
            return $config;
146
        }
147
148
        return $this->mergeServiceConfig($name, $class, $config);
149
    }
150
151
    /**
152
     * Find parent classes or interfaces and merge service configurations.
153
     *
154
     * @param string $name
155
     * @param string $class
156
     * @param array  $config
157
     *
158
     * @return array
159
     */
160
    protected function mergeServiceConfig(string $name, string $class, array $config): array
161
    {
162
        if (!class_exists($class)) {
163
            return $config;
164
        }
165
166
        $parents = array_merge(class_implements($class), class_parents($class));
167
        foreach ($parents as $parent) {
168
            if (isset($this->config[$parent])) {
169
                $config = array_merge($config, $this->config[$parent]);
170
            }
171
        }
172
173
        if (isset($this->config[$name])) {
174
            $config = array_merge($config, $this->config[$name]);
175
        }
176
177
        return $config;
178
    }
179
}
180