Container::share()   A
last analyzed

Complexity

Conditions 4
Paths 3

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 1
Metric Value
c 2
b 1
f 1
dl 0
loc 11
rs 9.2
cc 4
eloc 6
nc 3
nop 3
1
<?php
2
/*
3
 * This file is part of the Borobudur-DependencyInjection package.
4
 *
5
 * (c) Hexacodelabs <http://hexacodelabs.com>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace Borobudur\DependencyInjection;
12
13
use Borobudur\DependencyInjection\Exception\InvalidArgumentException;
14
use Borobudur\DependencyInjection\Exception\ServiceNotFoundException;
15
use Borobudur\DependencyInjection\ParameterBag\ImmutableParameterBag;
16
use Borobudur\DependencyInjection\ParameterBag\ParameterBagInterface;
17
18
/**
19
 * @author      Iqbal Maulana <[email protected]>
20
 * @created     8/8/15
21
 */
22
class Container implements ContainerInterface
23
{
24
    /**
25
     * @var array
26
     */
27
    protected $services = array();
28
29
    /**
30
     * @var array
31
     */
32
    protected $aliases = array();
33
34
    /**
35
     * @var ParameterBagInterface
36
     */
37
    protected $parameter;
38
39
    /**
40
     * @var Di
41
     */
42
    protected $di;
43
44
    /**
45
     * Constructor.
46
     *
47
     * @param ParameterBagInterface $parameterBag
48
     * @param Di                    $di
49
     */
50
    public function __construct(ParameterBagInterface $parameterBag = null, Di $di = null)
51
    {
52
        $this->parameter = $parameterBag ?: new ParameterBag();
53
        $this->di = $di ?: new Di($this);
54
    }
55
56
    /**
57
     * Compile parameter.
58
     *
59
     * Parameter become immutable.
60
     *
61
     * @return static
62
     */
63
    public function compile()
64
    {
65
        $this->parameter->getResolver()->resolve();
66
67
        $this->parameter = new ImmutableParameterBag($this->parameter->all());
68
69
        return $this;
70
    }
71
72
    /**
73
     * Check if container is immutable.
74
     *
75
     * @return bool
76
     */
77
    public function isImmutable()
78
    {
79
        return $this->parameter instanceof ImmutableParameterBag;
80
    }
81
82
    /**
83
     * {@inheritdoc}
84
     */
85
    public function set($id, $service)
86
    {
87
        if (false === is_callable($service) && false === is_object($service)) {
88
            throw new InvalidArgumentException(sprintf(
89
                'Service should be callable or object, "%s" given.',
90
                gettype($service)
91
            ));
92
        }
93
94
        if (is_object($service) && $service instanceof ContainerAwareInterface) {
95
            $service->setContainer($this);
96
        }
97
98
        $this->services[strtolower($id)] = $service;
99
    }
100
101
    /**
102
     * {@inheritdoc}
103
     */
104
    public function share($id, $service, array $args = array())
105
    {
106
        if (is_callable($service)) {
107
            $result = $this->getDi()->call($service, $args);
108
            if (is_callable($result) || is_object($result)) {
109
                $service = $result;
110
            }
111
        }
112
113
        $this->set($id, $service);
114
    }
115
116
    /**
117
     * {@inheritdoc}
118
     */
119
    public function get($id, array $args = array(), $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE)
120
    {
121
        $id = $this->getServiceId($id);
122
123
        if (isset($this->services[$id])) {
124
            return $this->callService($this->services[$id], $args);
125
        }
126
127
        if (self::NULL_ON_INVALID_REFERENCE === $invalidBehavior) {
128
            return null;
129
        }
130
131
        throw new ServiceNotFoundException($id, alternative($id, $this->services));
132
    }
133
134
    /**
135
     * Check if service id has alias.
136
     *
137
     * @param string $id
138
     *
139
     * @return bool
140
     */
141
    public function hasAlias($id)
142
    {
143
        foreach($this->aliases as $alias => $ids) {
144
            if (in_array($id, $ids)) {
145
                return true;
146
            }
147
        }
148
149
        return false;
150
    }
151
152
    /**
153
     * Get id from alias.
154
     *
155
     * @param string $id
156
     *
157
     * @return string|null
158
     */
159
    public function getAliasFromId($id)
160
    {
161
        foreach($this->aliases as $alias => $ids) {
162
            if (in_array($id, $ids)) {
163
                return $alias;
164
            }
165
        }
166
167
        return null;
168
    }
169
170
    /**
171
     * {@inheritdoc}
172
     */
173
    public function has($id)
174
    {
175
        return isset($this->aliases[$id]) || array_key_exists(strtolower($id), $this->services);
176
    }
177
178
    /**
179
     * {@inheritdoc}
180
     */
181
    public function getParameterBag()
182
    {
183
        return $this->parameter;
184
    }
185
186
    /**
187
     * Get instance builder.
188
     *
189
     * @return Di
190
     */
191
    public function getDi()
192
    {
193
        return $this->di;
194
    }
195
196
    /**
197
     * Execute service.
198
     *
199
     * @param mixed $service
200
     * @param array $args
201
     *
202
     * @return mixed
203
     */
204
    protected function callService($service, array $args = array())
205
    {
206
        if (is_callable($service)) {
207
            return $this->getDi()->call($service, $args);
208
        }
209
210
        return $service;
211
    }
212
213
    /**
214
     * Get service id.
215
     *
216
     * @param string $id
217
     *
218
     * @return string
219
     */
220
    protected function getServiceId($id)
221
    {
222
        if (isset($this->aliases[$id])) {
223
            return end($this->aliases[$id]);
224
        }
225
226
        return strtolower($id);
227
    }
228
}
229