Completed
Push — master ( cdbc95...331c43 )
by Miloš
01:18
created

Container::get()   B

Complexity

Conditions 8
Paths 14

Size

Total Lines 33

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 8.8337

Importance

Changes 0
Metric Value
cc 8
nc 14
nop 1
dl 0
loc 33
ccs 13
cts 17
cp 0.7647
crap 8.8337
rs 8.1475
c 0
b 0
f 0
1
<?php
2
3
namespace Laganica\Di;
4
5
use Closure;
6
use InvalidArgumentException;
7
use Laganica\Di\Definition\ClassDefinition;
8
use Laganica\Di\Definition\ClosureDefinition;
9
use Laganica\Di\Definition\Definition;
10
use Laganica\Di\Exception\ContainerException;
11
use Laganica\Di\Exception\NotFoundException;
12
use Laganica\Di\Resolver\ClassResolver;
13
use Laganica\Di\Resolver\ResolverFactoryInterface;
14
use Psr\Container\ContainerExceptionInterface;
15
use Psr\Container\ContainerInterface;
16
use Psr\Container\NotFoundExceptionInterface;
17
18
/**
19
 * Class Container
20
 *
21
 * @package Laganica\Di
22
 */
23
class Container implements ContainerInterface
24
{
25
    /**
26
     * @var array
27
     */
28
    private $definitions = [];
29
30
    /**
31
     * @var array
32
     */
33
    private $entries = [];
34
35
    /**
36
     * @var bool
37
     */
38
    private $autowire = true;
39
40
    /**
41
     * @var ResolverFactoryInterface
42
     */
43
    private $resolverFactory;
44
45
    /**
46
     * @param ResolverFactoryInterface $resolverFactory
47
     */
48 7
    public function __construct(ResolverFactoryInterface $resolverFactory)
49
    {
50 7
        $this->resolverFactory = $resolverFactory;
51 7
        $this->resolverFactory->setContainer($this);
52 7
    }
53
54
    /**
55
     * @inheritDoc
56
     */
57 7
    public function get($id)
58
    {
59 7
        if (!is_string($id)) {
60
            $type = gettype($id);
61
            throw new InvalidArgumentException("Argument \$id must be string, $type given");
62
        }
63
64 7
        if ($entry = $this->getEntry($id)) {
65
            return $entry;
66
        }
67
68 7
        $definition = $this->getDefinition($id);
69
70 7
        if ($definition instanceof Closure) {
71 1
            $definition = new ClosureDefinition($definition);
72
        }
73
74 7
        if (is_string($definition)) {
75 1
            $definition = new ClassDefinition($definition);
76
        }
77
78 7
        if ($definition && $resolver = $this->resolverFactory->create($definition)) {
79 7
            return $this->addEntry($id, $resolver->resolve($definition));
80
        }
81
82 6
        if ($this->isAutowire()) {
83 6
            $resolver = new ClassResolver($this);
84
85 6
            return $this->addEntry($id, $resolver->resolve(new ClassDefinition($id)));
86
        }
87
88
        throw NotFoundException::create($id);
89
    }
90
91
    /**
92
     * @inheritDoc
93
     */
94
    public function has($id): bool
95
    {
96
        try {
97
            $this->get($id);
98
99
            return true;
100
        } catch (NotFoundExceptionInterface $ex) {
101
            return false;
102
        } catch (ContainerExceptionInterface $ex) {
103
            return true;
104
        }
105
    }
106
107
    /**
108
     * @param bool $autowire
109
     */
110 7
    public function setAutowire(bool $autowire): void
111
    {
112 7
        $this->autowire = $autowire;
113 7
    }
114
115 6
    public function isAutowire(): bool
116
    {
117 6
        return $this->autowire;
118
    }
119
120
    /**
121
     * @param array $definitions
122
     *
123
     * @throws ContainerException
124
     */
125 7
    public function addDefinitions(array $definitions): void
126
    {
127 7
        foreach ($definitions as $id => $definition) {
128 7
            $this->addDefinition($id, $definition);
129
        }
130 7
    }
131
132
    /**
133
     * @param string $id
134
     * @param $definition
135
     *
136
     * @throws ContainerException
137
     */
138 7
    public function addDefinition(string $id, $definition): void
139
    {
140 7
        if ($this->hasDefinition($id)) {
141
            throw new ContainerException("More than one definition is found for entry or class $id");
142
        }
143
144 7
        $this->definitions[$id] = $definition;
145 7
    }
146
147
    /**
148
     * @param string $id
149
     *
150
     * @return null|mixed
151
     */
152 7
    public function getDefinition(string $id)
153
    {
154 7
        return $this->definitions[$id] ?? null;
155
    }
156
157
    /**
158
     * @param string $id
159
     *
160
     * @return bool
161
     */
162 7
    public function hasDefinition(string $id): bool
163
    {
164 7
        return array_key_exists($id, $this->definitions);
165
    }
166
167
    /**
168
     * @param string $id
169
     * @param mixed $entry
170
     *
171
     * @return mixed
172
     */
173 7
    private function addEntry(string $id, $entry)
174
    {
175 7
        return $this->entries[$id] = $entry;
176
    }
177
178
    /**
179
     * @param string $id
180
     *
181
     * @return null|mixed
182
     */
183 7
    public function getEntry(string $id)
184
    {
185 7
        return $this->entries[$id] ?? null;
186
    }
187
}
188