Completed
Push — master ( 331c43...fab006 )
by Miloš
01:13
created

Container::transformDefinition()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3

Importance

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