Completed
Push — 4.x ( 002a94...132f61 )
by Phil
01:28
created

Container::delegate()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 10
ccs 5
cts 5
cp 1
rs 9.9332
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace League\Container;
6
7
use League\Container\Definition\{DefinitionAggregate, DefinitionInterface, DefinitionAggregateInterface};
8
use League\Container\Exception\{NotFoundException, ContainerException};
9
use League\Container\Inflector\{InflectorAggregate, InflectorInterface, InflectorAggregateInterface};
10
use League\Container\ServiceProvider\{ServiceProviderAggregate,
11
    ServiceProviderAggregateInterface,
12
    ServiceProviderInterface};
13
use Psr\Container\ContainerInterface;
14
15
class Container implements DefinitionContainerInterface
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 108
    public function __construct(
43
        DefinitionAggregateInterface $definitions = null,
44
        ServiceProviderAggregateInterface $providers = null,
45
        InflectorAggregateInterface $inflectors = null
46
    ) {
47 108
        $this->definitions = $definitions ?? new DefinitionAggregate();
48 108
        $this->providers   = $providers   ?? new ServiceProviderAggregate();
49 108
        $this->inflectors  = $inflectors  ?? new InflectorAggregate();
50
51 108
        if ($this->definitions instanceof ContainerAwareInterface) {
52 108
            $this->definitions->setContainer($this);
53
        }
54
55 108
        if ($this->providers instanceof ContainerAwareInterface) {
56 108
            $this->providers->setContainer($this);
57
        }
58
59 108
        if ($this->inflectors instanceof ContainerAwareInterface) {
60 108
            $this->inflectors->setContainer($this);
61
        }
62 108
    }
63
64 24
    public function add(string $id, $concrete = null): DefinitionInterface
65
    {
66 24
        $concrete = $concrete ?? $id;
67
68 24
        if (true === $this->defaultToShared) {
69 3
            return $this->addShared($id, $concrete);
70
        }
71
72 21
        return $this->definitions->add($id, $concrete);
73
    }
74
75 6
    public function addShared(string $id, $concrete = null): DefinitionInterface
76
    {
77 6
        $concrete = $concrete ?? $id;
78 6
        return $this->definitions->addShared($id, $concrete);
79
    }
80
81 3
    public function defaultToShared(bool $shared = true): ContainerInterface
82
    {
83 3
        $this->defaultToShared = $shared;
84 3
        return $this;
85
    }
86
87 9
    public function extend(string $id): DefinitionInterface
88
    {
89 9
        if ($this->providers->provides($id)) {
90 3
            $this->providers->register($id);
91
        }
92
93 9
        if ($this->definitions->has($id)) {
94 6
            return $this->definitions->getDefinition($id);
95
        }
96
97 3
        throw new NotFoundException(sprintf(
98 3
            'Unable to extend alias (%s) as it is not being managed as a definition',
99 1
            $id
100
        ));
101
    }
102
103 9
    public function addServiceProvider($provider): DefinitionContainerInterface
104
    {
105 9
        $this->providers->add($provider);
106 9
        return $this;
107
    }
108
109 30
    public function get($id, bool $new = false)
110
    {
111 30
        if ($this->definitions->has($id)) {
112 18
            $resolved = $this->definitions->resolve($id, $new);
113 18
            return $this->inflectors->inflect($resolved);
114
        }
115
116 15
        if ($this->definitions->hasTag($id)) {
117 3
            $arrayOf = $this->definitions->resolveTagged($id, $new);
118
119
            array_walk($arrayOf, function (&$resolved) {
120 3
                $resolved = $this->inflectors->inflect($resolved);
121 3
            });
122
123 3
            return $arrayOf;
124
        }
125
126 12
        if ($this->providers->provides($id)) {
127 6
            $this->providers->register($id);
128
129 6
            if (!$this->definitions->has($id) && !$this->definitions->hasTag($id)) {
130 3
                throw new ContainerException(sprintf('Service provider lied about providing (%s) service', $id));
131
            }
132
133 3
            return $this->get($id, $new);
134
        }
135
136 6
        foreach ($this->delegates as $delegate) {
137 3
            if ($delegate->has($id)) {
138 3
                $resolved = $delegate->get($id);
139 3
                return $this->inflectors->inflect($resolved);
140
            }
141
        }
142
143 3
        throw new NotFoundException(sprintf('Alias (%s) is not being managed by the container or delegates', $id));
144
    }
145
146 33
    public function has($id): bool
147
    {
148 33
        if ($this->definitions->has($id)) {
149 18
            return true;
150
        }
151
152 18
        if ($this->definitions->hasTag($id)) {
153 3
            return true;
154
        }
155
156 15
        if ($this->providers->provides($id)) {
157 6
            return true;
158
        }
159
160 9
        foreach ($this->delegates as $delegate) {
161 3
            if ($delegate->has($id)) {
162 3
                return true;
163
            }
164
        }
165
166 6
        return false;
167
    }
168
169 3
    public function inflector(string $type, callable $callback = null): InflectorInterface
170
    {
171 3
        return $this->inflectors->add($type, $callback);
172
    }
173
174 3
    public function delegate(ContainerInterface $container): self
175
    {
176 3
        $this->delegates[] = $container;
177
178 3
        if ($container instanceof ContainerAwareInterface) {
179 3
            $container->setContainer($this);
180
        }
181
182 3
        return $this;
183
    }
184
}
185