Completed
Push — master ( 3cc274...d1e3f1 )
by Miloš
01:35 queued 13s
created

Container::addEntry()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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