Completed
Push — 3.x ( cf16f4...dd3fa1 )
by Phil
50:52 queued 49:27
created

Container   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 234
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 9

Test Coverage

Coverage 97.06%

Importance

Changes 0
Metric Value
wmc 28
lcom 1
cbo 9
dl 0
loc 234
ccs 66
cts 68
cp 0.9706
rs 10
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 21 4
A add() 0 7 1
A share() 0 4 1
A defaultToShared() 0 6 1
A extend() 0 14 3
A addServiceProvider() 0 6 1
B get() 0 36 8
A inflector() 0 4 1
A delegate() 0 10 2
B has() 0 22 6
1
<?php declare(strict_types=1);
2
3
namespace League\Container;
4
5
use League\Container\Definition\{DefinitionAggregate, DefinitionInterface, DefinitionAggregateInterface};
6
use League\Container\Exception\{NotFoundException, ContainerException};
7
use League\Container\Inflector\{InflectorAggregate, InflectorInterface, InflectorAggregateInterface};
8
use League\Container\ServiceProvider\{
9
    ServiceProviderAggregate,
10
    ServiceProviderAggregateInterface,
11
    ServiceProviderInterface
12
};
13
use Psr\Container\ContainerInterface;
14
15
class Container implements ContainerInterface
16
{
17
    /**
18
     * @var boolean
19
     */
20
    protected $defaultToShared = false;
21
22
    /**
23
     * @var DefinitionAggregateInterface
24
     */
25
    protected $definitions;
26
27
    /**
28
     * @var ServiceProviderAggregateInterface
29
     */
30
    protected $providers;
31
32
    /**
33
     * @var InflectorAggregateInterface
34
     */
35
    protected $inflectors;
36
37
    /**
38
     * @var ContainerInterface[]
39
     */
40
    protected $delegates = [];
41
42
    /**
43
     * Construct.
44
     *
45
     * @param DefinitionAggregateInterface|null      $definitions
46
     * @param ServiceProviderAggregateInterface|null $providers
47
     * @param InflectorAggregateInterface|null       $inflectors
48
     */
49 114
    public function __construct(
50
        DefinitionAggregateInterface      $definitions = null,
51
        ServiceProviderAggregateInterface $providers = null,
52
        InflectorAggregateInterface       $inflectors = null
53
    ) {
54 114
        $this->definitions = $definitions ?? new DefinitionAggregate;
55 114
        $this->providers   = $providers   ?? new ServiceProviderAggregate;
56 114
        $this->inflectors  = $inflectors  ?? new InflectorAggregate;
57
58 114
        if ($this->definitions instanceof ContainerAwareInterface) {
59 114
            $this->definitions->setLeagueContainer($this);
60
        }
61
62 114
        if ($this->providers instanceof ContainerAwareInterface) {
63 114
            $this->providers->setLeagueContainer($this);
64
        }
65
66 114
        if ($this->inflectors instanceof ContainerAwareInterface) {
67 114
            $this->inflectors->setLeagueContainer($this);
68
        }
69 114
    }
70
71
    /**
72
     * Add an item to the container.
73
     *
74
     * @param string  $id
75
     * @param mixed   $concrete
76
     * @param boolean $shared
77
     *
78
     * @return DefinitionInterface
79
     */
80 27
    public function add(string $id, $concrete = null, bool $shared = null) : DefinitionInterface
81
    {
82 27
        $concrete = $concrete ?? $id;
83 27
        $shared = $shared ?? $this->defaultToShared;
84
85 27
        return $this->definitions->add($id, $concrete, $shared);
86
    }
87
88
    /**
89
     * Proxy to add with shared as true.
90
     *
91
     * @param string $id
92
     * @param mixed  $concrete
93
     *
94
     * @return DefinitionInterface
95
     */
96 3
    public function share(string $id, $concrete = null) : DefinitionInterface
97
    {
98 3
        return $this->add($id, $concrete, true);
99
    }
100
101
    /**
102
     * Whether the container should default to defining shared definitions.
103
     *
104
     * @param boolean $shared
105
     *
106
     * @return self
107
     */
108 6
    public function defaultToShared(bool $shared = true) : ContainerInterface
109
    {
110 6
        $this->defaultToShared = $shared;
111
112 6
        return $this;
113
    }
114
115
    /**
116
     * Get a definition to extend.
117
     *
118
     * @param string $id [description]
119
     *
120
     * @return DefinitionInterface
121
     */
122 9
    public function extend(string $id) : DefinitionInterface
123
    {
124 9
        if ($this->providers->provides($id)) {
125 3
            $this->providers->register($id);
126
        }
127
128 9
        if ($this->definitions->has($id)) {
129 6
            return $this->definitions->getDefinition($id);
130
        }
131
132 3
        throw new NotFoundException(
133 3
            sprintf('Unable to extend alias (%s) as it is not being managed as a definition', $id)
134
        );
135
    }
136
137
    /**
138
     * Add a service provider.
139
     *
140
     * @param ServiceProviderInterface|string $provider
141
     *
142
     * @return self
143
     */
144 9
    public function addServiceProvider($provider) : self
145
    {
146 9
        $this->providers->add($provider);
147
148 9
        return $this;
149
    }
150
151
    /**
152
     * {@inheritdoc}
153
     */
154 33
    public function get($id, bool $new = false)
155
    {
156 33
        if ($this->definitions->has($id)) {
157 18
            $resolved = $this->definitions->resolve($id, $new);
158 18
            return $this->inflectors->inflect($resolved);
159
        }
160
161 18
        if ($this->definitions->hasTag($id)) {
162 3
            $arrayOf = $this->definitions->resolveTagged($id, $new);
163
164 2
            array_walk($arrayOf, function (&$resolved) {
165 3
                $resolved = $this->inflectors->inflect($resolved);
166 3
            });
167
168 3
            return $arrayOf;
169
        }
170
171 15
        if ($this->providers->provides($id)) {
172 6
            $this->providers->register($id);
173
174 6
            if (!$this->definitions->has($id) && !$this->definitions->hasTag($id)) {
175 3
                throw new ContainerException(sprintf('Service provider lied about providing (%s) service', $id));
176
            }
177
178 3
            return $this->get($id, $new);
179
        }
180
181 9
        foreach ($this->delegates as $delegate) {
182 3
            if ($delegate->has($id)) {
183 3
                $resolved = $delegate->get($id);
184 3
                return $this->inflectors->inflect($resolved);
185
            }
186
        }
187
188 6
        throw new NotFoundException(sprintf('Alias (%s) is not being managed by the container or delegates', $id));
189
    }
190
191
    /**
192
     * {@inheritdoc}
193
     */
194 27
    public function has($id) : bool
195
    {
196 27
        if ($this->definitions->has($id)) {
197 15
            return true;
198
        }
199
200 15
        if ($this->definitions->hasTag($id)) {
201 3
            return true;
202
        }
203
204 12
        if ($this->providers->provides($id)) {
205 6
            return true;
206
        }
207
208 6
        foreach ($this->delegates as $delegate) {
209
            if ($delegate->has($id)) {
210
                return true;
211
            }
212
        }
213
214 6
        return false;
215
    }
216
217
    /**
218
     * Allows for manipulation of specific types on resolution.
219
     *
220
     * @param string        $type
221
     * @param callable|null $callback
222
     *
223
     * @return InflectorInterface
224
     */
225 3
    public function inflector(string $type, callable $callback = null) : InflectorInterface
226
    {
227 3
        return $this->inflectors->add($type, $callback);
228
    }
229
230
    /**
231
     * Delegate a backup container to be checked for services if it
232
     * cannot be resolved via this container.
233
     *
234
     * @param ContainerInterface $container
235
     *
236
     * @return self
237
     */
238 3
    public function delegate(ContainerInterface $container) : self
239
    {
240 3
        $this->delegates[] = $container;
241
242 3
        if ($container instanceof ContainerAwareInterface) {
243 3
            $container->setLeagueContainer($this);
244
        }
245
246 3
        return $this;
247
    }
248
}
249