Passed
Push — master ( 81725e...2d0b63 )
by Raffael
02:13
created

Config::createServiceConfig()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 17
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 9
nc 8
nop 1
dl 0
loc 17
rs 9.2
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
            if (!is_string($config['use'])) {
70
                throw new Exception\InvalidConfiguration('use must be a string for service '.$name);
71
            }
72
        } else {
73
            $config['use'] = $name;
74
        }
75
76
        return $config;
77
    }
78
79
    /**
80
     * Parse env param.
81
     *
82
     * @param string $param
83
     *
84
     * @return string
85
     */
86
    public function getEnv(string $param): string
87
    {
88
        if (preg_match_all('#\{ENV\(([A-Za-z0-9_]+)(?:(,?)([^}]*))\)\}#', $param, $matches)) {
89
            if (4 !== count($matches)) {
90
                return $param;
91
            }
92
93
            for ($i = 0; $i < 1; ++$i) {
94
                $param = $this->parseEnv($param, $matches, $i);
95
            }
96
97
            return $param;
98
        }
99
100
        return $param;
101
    }
102
103
    /**
104
     * Parse env.
105
     *
106
     * @param string $param
107
     * @param array  $variables
108
     * @param int    $key
109
     *
110
     * @return string
111
     */
112
    protected function parseEnv(string $param, array $variables, int $key): string
113
    {
114
        $env = getenv($variables[1][$key]);
115
        if (false === $env && !empty($variables[3][$key])) {
116
            return str_replace($variables[0][$key], $variables[3][$key], $param);
117
        }
118
        if (false === $env) {
119
            throw new Exception\EnvVariableNotFound('env variable '.$variables[1][$key].' required but it is neither set not a default value exists');
120
        }
121
122
        return str_replace($variables[0][$key], $env, $param);
123
    }
124
125
    /**
126
     * Create service config.
127
     *
128
     * @param string $name
129
     *
130
     * @return array
131
     */
132
    protected function createServiceConfig(string $name): array
133
    {
134
        $config = [];
135
        if ($this->has($name)) {
136
            $config = $this->config[$name];
137
        }
138
139
        $class = $name;
140
        if (isset($config['use'])) {
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
        $parents = array_merge(class_implements($class), class_parents($class));
163
        foreach ($parents as $parent) {
164
            if (isset($this->config[$parent])) {
165
                $config = array_merge($config, $this->config[$parent]);
166
            }
167
        }
168
169
        if (isset($this->config[$name])) {
170
            $config = array_merge($config, $this->config[$name]);
171
        }
172
173
        return $config;
174
    }
175
}
176