Completed
Pull Request — master (#126)
by Phil
13:49
created

Container::has()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 18
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 18
ccs 11
cts 11
cp 1
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 9
nc 5
nop 1
crap 5
1
<?php declare(strict_types=1);
2
3
namespace League\Container;
4
5
use League\Container\Definition\{DefinitionAggregate, DefinitionInterface, DefinitionAggregateInterface};
6
use League\Container\Inflector\{InflectorAggregate, InflectorInterface, InflectorAggregateInterface};
7
use League\Container\ServiceProvider\{ServiceProviderAggregate, ServiceProviderAggregateInterface};
8
use Psr\Container\ContainerInterface;
9
10
class Container implements ContainerInterface
11
{
12
    /**
13
     * @var \League\Container\Definition\DefinitionAggregateInterface
14
     */
15
    protected $definitions;
16
17
    /**
18
     * @var \League\Container\ServiceProvider\ServiceProviderAggregateInterface
19
     */
20
    protected $providers;
21
22
    /**
23
     * @var \League\Container\Inflector\InflectorAggregateInterface
24
     */
25
    protected $inflectors;
26
27
    /**
28
     * @var \Psr\Container\ContainerInterface[]
29
     */
30
    protected $delegates = [];
31
32
    /**
33
     * Construct.
34
     *
35
     * @param \League\Container\Definition\DefinitionAggregateInterface|null           $definitions
36
     * @param \League\Container\ServiceProvider\ServiceProviderAggregateInterface|null $providers
37
     * @param \League\Container\Inflector\InflectorAggregateInterface|null             $inflectors
38
     */
39
    public function __construct(
40
        DefinitionAggregateInterface      $definitions = null,
41
        ServiceProviderAggregateInterface $providers   = null,
42
        InflectorAggregateInterface       $inflectors  = null
43
    ) {
44
        $this->definitions = $definitions ?? (new DefinitionAggregate)->setContainer($this);
45
        $this->providers   = $providers   ?? (new ServiceProviderAggregate)->setContainer($this);
46
        $this->inflectors  = $inflectors  ?? (new InflectorAggregate)->setContainer($this);
47
    }
48
49
    /**
50
     * Add an item to the container.
51
     *
52
     * @param string  $id
53
     * @param mixed   $concrete
54
     * @param boolean $shared
55
     *
56
     * @return \League\Container\Definition\DefinitionInterface
57
     */
58
    public function add(string $id, $concrete = null, bool $shared = false): DefinitionInterface
59
    {
60 57
        $concrete = $concrete ?? $id;
61
62
        return $this->definitions->add($id, $concrete, $shared);
63
    }
64
65
    /**
66 57
     * Get a definition to extend.
67 56
     *
68 39
     * @param string $id [description]
69
     *
70 57
     * @return \League\Container\Definition\DefinitionInterface
71 57
     */
72 38
    public function extend(string $id): DefinitionInterface
73
    {
74 57
        if ($this->providers->provides($id)) {
75 57
            $this->providers->register($id);
76 38
        }
77 57
78
        if ($this->definitions->has($id)) {
79
            return $this->definitions->getDefinition($id);
80
        }
81
82 45
        throw new NotFoundException(
83
            sprintf('Unable to extend alias (%s) as it is not being managed as a definition', $alias)
84
        );
85 45
    }
86 21
87 21
    /**
88 12
     * Add a service provider.
89
     *
90 12
     * @param \League\Container\ServiceProvider\ServiceProviderInterface|string $provider
91
     *
92
     * @return self
93 9
     */
94
    public function addServiceProvider($provider): self
95 6
    {
96
        $this->providers->add($provider);
97
98
        return $this;
99
    }
100
101
    /**
102 21
     * {@inheritdoc}
103
     */
104 21
    public function get($id, array $args = [], bool $new = false)
105 15
    {
106
        if ($this->definitions->has($id)) {
107
            $resolved = $this->definitions->resolve($id, $args, $new);
108 9
            return $this->inflectors->inflect($resolved);
109 3
        }
110
111
        if ($this->providers->provides($id)) {
112 9
            $this->providers->register($id);
113
            return $this->get($id, $args, $new);
114
        }
115
116
        foreach ($this->delegates as $delegate) {
117
            if ($delegate->has($id)) {
118
                $resolved = $delegate->get($id, $args);
1 ignored issue
show
Unused Code introduced by
The call to ContainerInterface::get() has too many arguments starting with $args.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
119
                return $this->inflectors->inflect($resolved);
120
            }
121
        }
122 51
123
        throw new NotFoundException(sprintf('Alias (%s) is not being managed by the container or delegates', $id));
124 51
    }
125
126 51
    /**
127
     * {@inheritdoc}
128
     */
129
    public function has($id): bool
130
    {
131
        if ($this->definitions->has($id)) {
132 45
            return true;
133
        }
134 45
135 45
        if ($this->providers->provides($id)) {
136 45
            return true;
137
        }
138 45
139 3
        foreach ($this->delegates as $delegate) {
140 2
            if ($delegate->has($id)) {
141
                return true;
142 45
            }
143
        }
144 45
145 39
        return false;
146 18
    }
147 12
148 33
    /**
149
     * Allows for manipulation of specific types on resolution.
150
     *
151 39
     * @param string        $type
152
     * @param callable|null $callback
153
     *
154
     * @return \League\Container\Inflector\InflectorInterface
155 6
     */
156 6
    public function inflector(string $type, callable $callback = null): InflectorInterface
157
    {
158
        return $this->inflectors->add($type, $callback);
159
    }
160
161 33
    /**
162
     * Delegate a backup container to be checked for services if it
163 33
     * cannot be resolved via this container.
164
     *
165
     * @param \Psr\Container\ContainerInterface $container
166
     *
167
     * @return self
168
     */
169 12
    public function delegate(ContainerInterface $container): self
170
    {
171 12
        $this->delegates[] = $container;
172
173 12
        if ($container instanceof ContainerAwareInterface) {
174
            $container->setContainer($this);
175
        }
176
177
        return $this;
178
    }
179
}
180