Completed
Push — master ( c780b9...d0dcc2 )
by Andy
01:32
created

Container::hasParameter()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 1
nc 2
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Palmtree\Container;
4
5
use Palmtree\Container\Definition\Definition;
6
use Palmtree\Container\Exception\ParameterNotFoundException;
7
use Palmtree\Container\Exception\ServiceNotFoundException;
8
use Psr\Container\ContainerInterface;
9
10
class Container implements ContainerInterface
11
{
12
    /** Regex for parameters e.g '%my.parameter%' */
13
    const PATTERN_PARAMETER = '/^%([^%]+)%$/';
14
    /** Regex for environment variable parameters e.g '%env(MY_ENV_VAR)%' */
15
    const PATTERN_ENV_PARAMETER = '/^env\(([^\)]+)\)$/';
16
    /** Regex for services e.g '@myservice' */
17
    const PATTERN_SERVICE = '/^@(.+)$/';
18
19
    /** @var Definition[]|mixed[] */
20
    protected $services = [];
21
    /** @var array */
22
    protected $parameters = [];
23
24
    /** @var array */
25
    protected $envCache = [];
26
27 11
    public function __construct(array $services = [], array $parameters = [])
28
    {
29 11
        foreach ($services as $key => $definitionArgs) {
30 11
            $this->add($key, $definitionArgs);
31
        }
32
33 11
        $this->parameters = $parameters;
34 11
        $this->parameters = $this->resolveArgs($this->parameters);
35
36
        // Instantiate non-lazy services
37 11
        foreach ($this->services as $key => $service) {
38 11
            if ($service instanceof Definition && !$service->isLazy()) {
39 11
                $this->get($key);
40
            }
41
        }
42 11
    }
43
44
    /**
45
     * @param string $key
46
     * @param mixed  $default
47
     *
48
     * @return mixed
49
     * @throws ParameterNotFoundException
50
     */
51 11
    public function getParameter($key, $default = null)
52
    {
53 11
        if (!$this->hasParameter($key)) {
54 1
            if (func_num_args() < 2) {
55 1
                throw new ParameterNotFoundException($key);
56
            }
57
58
            return $default;
59
        }
60
61 11
        return $this->parameters[$key];
62
    }
63
64
    /**
65
     * @param $key
66
     * @param $value
67
     *
68
     * @throws ParameterNotFoundException
69
     * @throws ServiceNotFoundException
70
     */
71 11
    public function setParameter($key, $value)
72
    {
73 11
        $this->parameters[$key] = $this->resolveArg($value);
74 11
    }
75
76
    /**
77
     * @param string $key
78
     *
79
     * @return bool
80
     */
81 11
    public function hasParameter($key)
82
    {
83 11
        return isset($this->parameters[$key]) || array_key_exists($key, $this->parameters);
84
    }
85
86
    /**
87
     * @param string $key
88
     *
89
     * @return bool
90
     */
91 11
    public function has($key)
92
    {
93 11
        return isset($this->services[$key]) || array_key_exists($key, $this->services);
94
    }
95
96
    /**
97
     * @param string $key
98
     *
99
     * @return mixed
100
     * @throws ServiceNotFoundException
101
     */
102 11
    public function get($key)
103
    {
104 11
        if (!$this->has($key)) {
105 1
            throw new ServiceNotFoundException($key);
106
        }
107
108 11
        $service = $this->services[$key];
109
110 11
        if ($service instanceof Definition) {
111 11
            $service = $this->create($service);
112
        }
113
114 11
        return $this->services[$key] = $service;
115
    }
116
117
    /**
118
     * @param string $key
119
     * @param array  $definitionArgs
120
     *
121
     * @return Definition
122
     */
123 11
    protected function add($key, array $definitionArgs)
124
    {
125 11
        return $this->services[$key] = Definition::fromYaml($definitionArgs);
126
    }
127
128
    /**
129
     * Creates a service as defined by the Definition object.
130
     *
131
     * @param Definition $definition
132
     *
133
     * @return mixed
134
     */
135 11
    protected function create(Definition $definition)
136
    {
137 11
        $class = $definition->getClass();
138 11
        $args  = $this->resolveArgs($definition->getArguments());
139
140 11
        $service = new $class(...$args);
141
142 11
        foreach ($definition->getMethodCalls() as $methodCall) {
143 11
            $methodName = $methodCall->getName();
144 11
            $methodArgs = $this->resolveArgs($methodCall->getArguments());
145 11
            $service->$methodName(...$methodArgs);
146
        }
147
148 11
        return $service;
149
    }
150
151
    /**
152
     * @param array $args
153
     *
154
     * @return array
155
     */
156 11
    protected function resolveArgs(array $args)
157
    {
158 11
        foreach ($args as $key => &$arg) {
159 11
            if (is_array($arg)) {
160
                $arg = $this->resolveArgs($arg);
161
            } else {
162 11
                $arg = $this->resolveArg($arg);
163
            }
164
        }
165
166 11
        return $args;
167
    }
168
169
    /**
170
     * @param $arg
171
     *
172
     * @return mixed|string
173
     * @throws ParameterNotFoundException
174
     * @throws ServiceNotFoundException
175
     */
176 11
    protected function resolveArg($arg)
177
    {
178 11
        if (is_string($arg)) {
179 11
            if (preg_match(static::PATTERN_PARAMETER, $arg, $matches)) {
180 11
                $parameter = $matches[1];
181
182 11
                if (preg_match(static::PATTERN_ENV_PARAMETER, $parameter, $envMatches)) {
183 11
                    $arg = $this->getEnv($envMatches[1]);
184
                } else {
185 11
                    $arg = $this->getParameter($parameter);
186
                }
187 11
            } elseif (preg_match(static::PATTERN_SERVICE, $arg, $matches)) {
188 11
                $arg = $this->get($matches[1]);
189
            }
190
        }
191
192 11
        return $arg;
193
    }
194
195
    /**
196
     * @param string $key
197
     *
198
     * @return string
199
     */
200 11
    protected function getEnv($key)
201
    {
202 11
        if (isset($this->envCache[$key]) || array_key_exists($key, $this->envCache)) {
203
            return $this->envCache[$key];
204
        }
205
206 11
        $envVar = getenv($key);
207
208 11
        if (!$envVar) {
209 10
            $envVar = $this->getParameter(sprintf('env(%s)', $key));
210
        }
211
212 11
        if ($envVar) {
213 11
            $this->envCache[$key] = $this->resolveArg($envVar);
214
        }
215
216 11
        return $this->envCache[$key];
217
    }
218
}
219