Completed
Push — master ( ffbaaa...351c32 )
by Taosikai
12:15
created

Container::offsetGet()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
/*
4
 * This file is part of the slince/di package.
5
 *
6
 * (c) Slince <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Slince\Di;
13
14
use Slince\Di\Exception\DependencyInjectionException;
15
use Slince\Di\Exception\NotFoundException;
16
use Interop\Container\ContainerInterface;
17
18
class Container implements \ArrayAccess, ContainerInterface
19
{
20
    /**
21
     * @var array
22
     */
23
    protected $aliases = [];
24
25
    /**
26
     * Array of Definitions.
27
     *
28
     * @var Definition[]
29
     */
30
    protected $definitions = [];
31
32
    /**
33
     * @var array
34
     */
35
    protected $instances;
36
37
    /**
38
     * Array of parameters.
39
     *
40
     * @var ParameterBag
41
     */
42
    protected $parameters;
43
44
    /**
45
     * @var Resolver
46
     */
47
    protected $resolver;
48
49
    /**
50
     * Defaults for the container.
51
     *
52
     * [
53
     *     'share' => true,
54
     *     'autowire' => true
55
     * ]
56
     *
57
     * @var array
58
     */
59
    protected $defaults = [
60
        'share' => true,
61
        'autowire' => true,
62
    ];
63
64
    public function __construct()
65
    {
66
        $this->parameters = new ParameterBag();
67
        $this->resolver = new Resolver($this);
68
        $this->register($this);
69
    }
70
71
    /**
72
     * Determine if a given offset exists.
73
     *
74
     * @param string $key
75
     *
76
     * @return bool
77
     */
78
    public function offsetExists($key)
79
    {
80
        return $this->has($key);
81
    }
82
83
    /**
84
     * Get the value at a given offset.
85
     *
86
     * @param string $key
87
     *
88
     * @return mixed
89
     */
90
    public function offsetGet($key)
91
    {
92
        return $this->get($key);
93
    }
94
95
    /**
96
     * Set the value at a given offset.
97
     *
98
     * @param string $key
99
     * @param mixed  $value
100
     */
101
    public function offsetSet($key, $value)
102
    {
103
        $this->register($key, $value);
104
    }
105
106
    /**
107
     * Unset the value at a given offset.
108
     *
109
     * @param string $key
110
     */
111
    public function offsetUnset($key)
112
    {
113
        unset($this->definitions[$key], $this->instances[$key]);
114
    }
115
116
    /**
117
     * Register a definition.
118
     *
119
     * @param string|object $id
120
     * @param mixed         $concrete
121
     *
122
     * @return Definition
123
     */
124
    public function register($id, $concrete = null)
125
    {
126
        if (null === $concrete) {
127
            $concrete = $id;
128
        }
129
        if (is_object($id)) {
130
            $id = get_class($id);
131
        }
132
        //Apply defaults.
133
        $definition = (new Definition($concrete))
134
            ->setShared($this->defaults['share'])
135
            ->setAutowired($this->defaults['autowire']);
136
137
        $definition = $this->setDefinition($id, $definition);
138
139
        return $definition;
140
    }
141
142
    /**
143
     * Set a definition.
144
     *
145
     * @param string     $id
146
     * @param Definition $definition
147
     *
148
     * @return Definition
149
     */
150
    public function setDefinition($id, Definition $definition)
151
    {
152
        $id = (string) $id;
153
154
        return $this->definitions[$id] = $definition;
155
    }
156
157
    /**
158
     * Sets an alias for an existing service.
159
     *
160
     * @param string $alias
161
     * @param string $id
162
     */
163
    public function setAlias($alias, $id)
164
    {
165
        $this->aliases[$alias] = $id;
166
    }
167
168
    /**
169
     * Get id of the alias.
170
     *
171
     * @param string $alias
172
     *
173
     * @return string|null
174
     */
175
    public function getAlias($alias)
176
    {
177
        return isset($this->aliases[$alias]) ? $this->aliases[$alias] : null;
178
    }
179
180
    /**
181
     * Get a service instance by specified ID.
182
     *
183
     * @param string $id
184
     *
185
     * @return object
186
     */
187
    public function get($id)
188
    {
189
        if (isset($this->aliases[$id])) {
190
            $id = $this->aliases[$id];
191
        }
192
        if (isset($this->instances[$id])) {
193
            return $this->instances[$id];
194
        }
195
196
        //If there is no matching definition, creates a definition.
197
        if (!$this->has($id) && class_exists($id)) {
198
            $this->register($id);
199
        }
200
        if (!$this->has($id)) {
201
            throw new NotFoundException(sprintf('There is no definition named "%s"', $id));
202
        }
203
        // resolve instance.
204
        $instance = $this->resolver->resolve($this->definitions[$id]);
205
        if ($this->definitions[$id]->isShared()) {
206
            $this->instances[$id] = $instance;
207
        }
208
209
        return $instance;
210
    }
211
212
    /**
213
     * {@inheritdoc}
214
     */
215
    public function has($id)
216
    {
217
        return isset($this->definitions[$id]);
218
    }
219
220
    /**
221
     * Extends a definition.
222
     *
223
     * @param string $id
224
     *
225
     * @return Definition
226
     */
227
    public function extend($id)
228
    {
229
        if (!$this->has($id)) {
230
            throw new NotFoundException(sprintf('There is no definition named "%s"', $id));
231
        }
232
        $definition = $this->definitions[$id];
233
        if ($definition->getResolved()) {
234
            throw new DependencyInjectionException(sprintf('Cannot override frozen service "%s".', $id));
235
        }
236
237
        return $definition;
238
    }
239
240
    /**
241
     * Returns service ids for a given tag.
242
     *
243
     * Example:
244
     *
245
     *     $container->register('foo')->addTag('my.tag', array('hello' => 'world'));
246
     *
247
     *     $serviceIds = $container->findTaggedServiceIds('my.tag');
248
     *     foreach ($serviceIds as $serviceId => $tags) {
249
     *         foreach ($tags as $tag) {
250
     *             echo $tag['hello'];
251
     *         }
252
     *     }
253
     *
254
     * @param string $name
255
     *
256
     * @return array
257
     */
258
    public function findTaggedServiceIds($name)
259
    {
260
        $tags = array();
261
        foreach ($this->definitions as $id => $definition) {
262
            if ($definition->hasTag($name)) {
263
                $tags[$id] = $definition->getTag($name);
264
            }
265
        }
266
267
        return $tags;
268
    }
269
270
    /**
271
     * Gets all global parameters.
272
     *
273
     * @return array
274
     */
275
    public function getParameters()
276
    {
277
        return $this->parameters->toArray();
278
    }
279
280
    /**
281
     * Sets array of parameters.
282
     *
283
     * @param array $parameterStore
284
     */
285
    public function setParameters(array $parameterStore)
286
    {
287
        $this->parameters->setParameters($parameterStore);
288
    }
289
290
    /**
291
     * Add some parameters.
292
     *
293
     * @param array $parameters
294
     */
295
    public function addParameters(array $parameters)
296
    {
297
        $this->parameters->addParameters($parameters);
298
    }
299
300
    /**
301
     * Sets a parameter with its name and value.
302
     *
303
     * @param $name
304
     * @param mixed $value
305
     */
306
    public function setParameter($name, $value)
307
    {
308
        $this->parameters->setParameter($name, $value);
309
    }
310
311
    /**
312
     * Gets a parameter by given name.
313
     *
314
     * @param $name
315
     * @param mixed $default
316
     *
317
     * @return mixed
318
     */
319
    public function getParameter($name, $default = null)
320
    {
321
        return $this->parameters->getParameter($name, $default);
322
    }
323
324
    /**
325
     * Gets a default option of the container.
326
     *
327
     * @param string $option
328
     *
329
     * @return mixed|null|boolean
330
     */
331
    public function getDefault($option)
332
    {
333
        return isset($this->defaults[$option]) ? $this->defaults[$option] : null;
334
    }
335
336
    /**
337
     * Configure defaults.
338
     *
339
     * @param array $defaults
340
     *
341
     * @return array
342
     */
343
    public function setDefaults(array $defaults)
344
    {
345
        return $this->defaults = array_merge($this->defaults, $defaults);
346
    }
347
}
348