Completed
Push — master ( 97da99...845621 )
by Andy
03:23
created

Container::inject()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 9
ccs 4
cts 4
cp 1
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Palmtree\Container;
4
5
use Palmtree\Container\Definition\Definition;
6
use Palmtree\Container\Exception\ParameterNotFoundException;
7
use Palmtree\Container\Exception\ServiceNotFoundException;
8
use Palmtree\Container\Exception\ServiceNotPublicException;
9
use Psr\Container\ContainerInterface;
10
11
class Container implements ContainerInterface
12
{
13
    /** @var Definition[] */
14
    private $definitions = [];
15
    /** @var mixed[] */
16
    private $services = [];
17
    /** @var array */
18
    private $parameters = [];
19
    /** @var Resolver */
20
    private $resolver;
21
22 25
    public function __construct(array $definitions = [], array $parameters = [])
23
    {
24 25
        foreach ($definitions as $key => $definitionArgs) {
25 22
            $this->addDefinition($key, Definition::fromYaml($definitionArgs));
26
        }
27
28 25
        $this->resolver = new Resolver($this, $this->services);
29
30 25
        $this->parameters = $parameters;
31 25
        $this->parameters = $this->resolver->resolveArgs($this->parameters);
32 25
    }
33
34
    /**
35
     * Instantiates non-lazy services.
36
     */
37 24
    public function instantiateServices()
38
    {
39 24
        foreach ($this->definitions as $key => $definition) {
40 22
            if (!$definition->isLazy()) {
41 22
                $this->services[$key] = $this->create($definition);
42
            }
43
        }
44 24
    }
45
46
    /**
47
     * Returns whether a service with the given key exists within the container.
48
     *
49
     * @param string $key
50
     *
51
     * @return bool
52
     */
53 23
    public function has($key)
54
    {
55 23
        return isset($this->services[$key]);
56
    }
57
58
    /**
59
     * Returns a service object with the given key.
60
     *
61
     * @param string $key
62
     *
63
     * @return mixed
64
     * @throws ServiceNotFoundException
65
     * @throws ServiceNotPublicException
66
     */
67 23
    public function get($key)
68
    {
69 23
        if (!$this->has($key)) {
70 22
            if (!$this->hasDefinition($key)) {
71 1
                throw new ServiceNotFoundException($key);
72
            }
73
74 22
            $this->services[$key] = $this->create($this->definitions[$key]);
75
        }
76
77 23
        if (!$this->definitions[$key]->isPublic()) {
78 21
            throw new ServiceNotPublicException($key);
79
        }
80
81 23
        return $this->services[$key];
82
    }
83
84
    /**
85
     * Returns whether a definition with the given key exists within the container.
86
     *
87
     * @param string $key
88
     *
89
     * @return bool
90
     */
91 22
    public function hasDefinition(string $key): bool
92
    {
93 22
        return isset($this->definitions[$key]);
94
    }
95
96 23
    public function addDefinition(string $key, Definition $definition)
97
    {
98 23
        $this->definitions[$key] = $definition;
99 23
    }
100
101
    /**
102
     * Returns a parameter with the given key or a default value if given.
103
     *
104
     * @param string $key
105
     * @param mixed  $default
106
     *
107
     * @return mixed
108
     * @throws ParameterNotFoundException
109
     */
110 22
    public function getParameter(string $key, $default = null)
111
    {
112 22
        if (!$this->hasParameter($key)) {
113 2
            if (func_num_args() < 2) {
114 1
                throw new ParameterNotFoundException($key);
115
            }
116
117 1
            return $default;
118
        }
119
120 22
        return $this->parameters[$key];
121
    }
122
123
    /**
124
     * Sets a parameter within the container.
125
     *
126
     * @param string $key
127
     * @param mixed  $value
128
     *
129
     * @throws ParameterNotFoundException
130
     * @throws ServiceNotFoundException
131
     */
132 21
    public function setParameter(string $key, $value)
133
    {
134 21
        $this->parameters[$key] = $this->resolver->resolveArg($value);
135 21
    }
136
137
    /**
138
     * Returns whether a parameter with the given key exists within the container.
139
     *
140
     * @param string $key
141
     *
142
     * @return bool
143
     */
144 22
    public function hasParameter(string $key): bool
145
    {
146 22
        return isset($this->parameters[$key]) || array_key_exists($key, $this->parameters);
147
    }
148
149
    /**
150
     * Creates a service as defined by the Definition object.
151
     *
152
     * @param Definition $definition
153
     *
154
     * @return mixed
155
     */
156 23
    private function create(Definition $definition)
157
    {
158 23
        $args = $this->resolver->resolveArgs($definition->getArguments());
159
160 23
        if ($factory = $definition->getFactory()) {
161 21
            list($class, $method) = $factory;
162 21
            $class   = $this->resolver->resolveArg($class);
163 21
            $method  = $this->resolver->resolveArg($method);
164 21
            $service = $class::$method(...$args);
165
        } else {
166 23
            $class   = $this->resolver->resolveArg($definition->getClass());
167 23
            $service = new $class(...$args);
168
        }
169
170 23
        foreach ($definition->getMethodCalls() as $methodCall) {
171 22
            $methodName = $methodCall->getName();
172 22
            $methodArgs = $this->resolver->resolveArgs($methodCall->getArguments());
173 22
            $service->$methodName(...$methodArgs);
174
        }
175
176 23
        return $service;
177
    }
178
}
179