Completed
Push — master ( 4cacbc...f20c98 )
by Miloš
01:28
created

Container::useAnnotations()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Laganica\Di;
4
5
use ArrayObject;
6
use InvalidArgumentException;
7
use Laganica\Di\Definition\ClassDefinition;
8
use Laganica\Di\Definition\DefinitionFactoryInterface;
9
use Laganica\Di\Definition\DefinitionInterface;
10
use Laganica\Di\Exception\CircularDependencyFoundException;
11
use Laganica\Di\Exception\ContainerException;
12
use Laganica\Di\Exception\DefinitionNotFoundException;
13
use Laganica\Di\Exception\InvalidDefinitionException;
14
use Laganica\Di\Exception\ClassNotFoundException;
15
use Laganica\Di\Resolver\ResolverFactoryInterface;
16
use Psr\Container\ContainerExceptionInterface;
17
use Psr\Container\ContainerInterface;
18
use Psr\Container\NotFoundExceptionInterface;
19
20
/**
21
 * Class Container
22
 *
23
 * @package Laganica\Di
24
 */
25
class Container implements ContainerInterface
26
{
27
    /**
28
     * @var ArrayObject
29
     */
30
    private $definitions;
31
32
    /**
33
     * @var ArrayObject
34
     */
35
    private $entries;
36
37
    /**
38
     * @var ArrayObject
39
     */
40
    private $resolving;
41
42
    /**
43
     * @var bool
44
     */
45
    private $useAutowiring;
46
47
    /**
48
     * @var bool
49
     */
50
    private $useAnnotations;
51
52
    /**
53
     * @var ResolverFactoryInterface
54
     */
55
    private $resolverFactory;
56
57
    /**
58
     * @var DefinitionFactoryInterface
59
     */
60
    private $definitionFactory;
61
62
    /**
63
     * @param DefinitionFactoryInterface $definitionFactory
64
     * @param ResolverFactoryInterface $resolverFactory
65
     */
66 20
    public function __construct(DefinitionFactoryInterface $definitionFactory, ResolverFactoryInterface $resolverFactory)
67
    {
68 20
        $this->definitions = new ArrayObject();
69 20
        $this->entries = new ArrayObject();
70 20
        $this->resolving = new ArrayObject();
71 20
        $this->definitionFactory = $definitionFactory;
72 20
        $this->resolverFactory = $resolverFactory;
73 20
        $this->resolverFactory->setContainer($this);
74 20
    }
75
76
    /**
77
     * @inheritDoc
78
     */
79 20
    public function get($id)
80
    {
81 20
        if (!is_string($id)) {
82 2
            $type = is_object($id) ? get_class($id) : gettype($id);
83 2
            throw new InvalidArgumentException("Argument \$id must be string, $type given");
84
        }
85
86 18
        if ($this->entries->offsetExists($id)) {
87 2
            return $this->entries->offsetGet($id);
88
        }
89
90 18
        $entry = $this->resolveEntry($id);
91 10
        $this->entries->offsetSet($id, $entry);
92
93 10
        return $entry;
94
    }
95
96
    /**
97
     * @inheritDoc
98
     */
99 3
    public function has($id): bool
100
    {
101
        try {
102 3
            $this->get($id);
103
104 1
            return true;
105 2
        } catch (NotFoundExceptionInterface $ex) {
106 1
            return false;
107 1
        } catch (ContainerExceptionInterface $ex) {
108 1
            return true;
109
        }
110
    }
111
112
    /**
113
     * @param string $id
114
     *
115
     * @throws CircularDependencyFoundException
116
     * @throws ClassNotFoundException
117
     * @throws ContainerException
118
     * @throws DefinitionNotFoundException
119
     * @throws InvalidDefinitionException
120
     *
121
     * @return mixed
122
     */
123 18
    private function resolveEntry(string $id)
124
    {
125 18
        $definition = $this->getDefinition($id);
126
127 16
        $this->startResolving($id);
128 16
        $entry = $this->resolverFactory->create($definition)->resolve($definition);
129 10
        $this->endResolving($id);
130
131 10
        return $entry;
132
    }
133
134
    /**
135
     * @param bool $useAutowiring
136
     */
137 20
    public function useAutowiring(bool $useAutowiring): void
138
    {
139 20
        $this->useAutowiring = $useAutowiring;
140 20
    }
141
142
    /**
143
     * @return bool
144
     */
145 12
    private function hasAutowiringEnabled(): bool
146
    {
147 12
        return $this->useAutowiring;
148
    }
149
150
    /**
151
     * @param bool $useAnnotations
152
     */
153 20
    public function useAnnotations(bool $useAnnotations): void
154
    {
155 20
        $this->useAnnotations = $useAnnotations;
156 20
    }
157
158
    /**
159
     * @return bool
160
     */
161 9
    public function hasAnnotationsEnabled(): bool
162
    {
163 9
        return $this->useAnnotations;
164
    }
165
166
    /**
167
     * @param ArrayObject $definitions
168
     */
169 20
    public function setDefinitions(ArrayObject $definitions): void
170
    {
171 20
        $this->definitions = $definitions;
172 20
    }
173
174
    /**
175
     * @param string $id
176
     *
177
     * @throws DefinitionNotFoundException
178
     * @throws InvalidDefinitionException
179
     *
180
     * @return DefinitionInterface
181
     */
182 18
    private function getDefinition(string $id): DefinitionInterface
183
    {
184 18
        $definition = $this->definitions->offsetExists($id)
185 13
            ? $this->definitions->offsetGet($id)
186 18
            : null;
187
188 18
        if ($definition === null && $this->hasAutowiringEnabled()) {
189 11
            $definition = new ClassDefinition($id);
190
        }
191
192 18
        if ($definition === null) {
193 1
            throw DefinitionNotFoundException::create($id);
194
        }
195
196 17
        return $this->definitionFactory->create($definition);
197
    }
198
199
    /**
200
     * @param string $id
201
     *
202
     * @throws CircularDependencyFoundException
203
     *
204
     * @return void
205
     */
206 16
    private function startResolving(string $id): void
207
    {
208 16
        if ($this->resolving->offsetExists($id)) {
209 1
            throw CircularDependencyFoundException::create($id);
210
        }
211
212 16
        $this->resolving->offsetSet($id, true);
213 16
    }
214
215
    /**
216
     * @param string $id
217
     *
218
     * @return void
219
     */
220 10
    private function endResolving(string $id): void
221
    {
222 10
        if ($this->resolving->offsetExists($id)) {
223 10
            $this->resolving->offsetUnset($id);
224
        }
225 10
    }
226
}
227