Completed
Push — 3.x ( 792756...40aed0 )
by Phil
02:52
created

Definition   A

Complexity

Total Complexity 31

Size/Duplication

Total Lines 267
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 5

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 31
lcom 2
cbo 5
dl 0
loc 267
ccs 72
cts 72
cp 1
rs 9.92
c 0
b 0
f 0

17 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
A addTag() 0 6 1
A hasTag() 0 4 1
A setAlias() 0 6 1
A getAlias() 0 4 1
A setShared() 0 6 1
A isShared() 0 4 1
A getConcrete() 0 4 1
A setConcrete() 0 7 1
A addArgument() 0 6 1
A addArguments() 0 8 2
A addMethodCall() 0 9 1
A addMethodCalls() 0 8 2
C resolve() 0 38 12
A resolveCallable() 0 6 1
A resolveClass() 0 7 1
A invokeMethods() 0 12 2
1
<?php declare(strict_types=1);
2
3
namespace League\Container\Definition;
4
5
use League\Container\Argument\{
6
    ArgumentResolverInterface, ArgumentResolverTrait, ClassNameInterface, RawArgumentInterface
7
};
8
use League\Container\ContainerAwareTrait;
9
use ReflectionClass;
10
use ReflectionException;
11
12
class Definition implements ArgumentResolverInterface, DefinitionInterface
13
{
14
    use ArgumentResolverTrait;
15
    use ContainerAwareTrait;
16
17
    /**
18
     * @var string
19
     */
20
    protected $alias;
21
22
    /**
23
     * @var mixed
24
     */
25
    protected $concrete;
26
27
    /**
28
     * @var boolean
29
     */
30
    protected $shared = false;
31
32
    /**
33
     * @var array
34
     */
35
    protected $tags = [];
36
37
    /**
38
     * @var array
39
     */
40
    protected $arguments = [];
41
42
    /**
43
     * @var array
44
     */
45
    protected $methods = [];
46
47
    /**
48
     * @var mixed
49
     */
50
    protected $resolved;
51
52
    /**
53
     * Constructor.
54
     *
55
     * @param string $id
56
     * @param mixed  $concrete
57
     */
58 69
    public function __construct(string $id, $concrete = null)
59
    {
60 69
        $concrete = $concrete ?? $id;
61
62 69
        $this->alias    = $id;
63 69
        $this->concrete = $concrete;
64 69
    }
65
66
    /**
67
     * {@inheritdoc}
68
     */
69 6
    public function addTag(string $tag) : DefinitionInterface
70
    {
71 6
        $this->tags[$tag] = true;
72
73 6
        return $this;
74
    }
75
76
    /**
77
     * {@inheritdoc}
78
     */
79 6
    public function hasTag(string $tag) : bool
80
    {
81 6
        return isset($this->tags[$tag]);
82
    }
83
84
    /**
85
     * {@inheritdoc}
86
     */
87 36
    public function setAlias(string $id) : DefinitionInterface
88
    {
89 36
        $this->alias = $id;
90
91 36
        return $this;
92
    }
93
94
    /**
95
     * {@inheritdoc}
96
     */
97 33
    public function getAlias() : string
98
    {
99 33
        return $this->alias;
100
    }
101
102
    /**
103
     * {@inheritdoc}
104
     */
105 39
    public function setShared(bool $shared = true) : DefinitionInterface
106
    {
107 39
        $this->shared = $shared;
108
109 39
        return $this;
110
    }
111
112
    /**
113
     * {@inheritdoc}
114
     */
115 45
    public function isShared() : bool
116
    {
117 45
        return $this->shared;
118
    }
119
120
    /**
121
     * {@inheritdoc}
122
     */
123 6
    public function getConcrete()
124
    {
125 6
        return $this->concrete;
126
    }
127
128
    /**
129
     * {@inheritdoc}
130
     */
131 3
    public function setConcrete($concrete) : DefinitionInterface
132
    {
133 3
        $this->concrete = $concrete;
134 3
        $this->resolved = null;
135
136 3
        return $this;
137
    }
138
139
    /**
140
     * {@inheritdoc}
141
     */
142 15
    public function addArgument($arg) : DefinitionInterface
143
    {
144 15
        $this->arguments[] = $arg;
145
146 15
        return $this;
147
    }
148
149
    /**
150
     * {@inheritdoc}
151
     */
152 3
    public function addArguments(array $args) : DefinitionInterface
153
    {
154 3
        foreach ($args as $arg) {
155 3
            $this->addArgument($arg);
156
        }
157
158 3
        return $this;
159
    }
160
161
    /**
162
     * {@inheritdoc}
163
     */
164 3
    public function addMethodCall(string $method, array $args = []) : DefinitionInterface
165
    {
166 3
        $this->methods[] = [
167 3
            'method'    => $method,
168 3
            'arguments' => $args
169
        ];
170
171 3
        return $this;
172
    }
173
174
    /**
175
     * {@inheritdoc}
176
     */
177 3
    public function addMethodCalls(array $methods = []) : DefinitionInterface
178
    {
179 3
        foreach ($methods as $method => $args) {
180 3
            $this->addMethodCall($method, $args);
181
        }
182
183 3
        return $this;
184
    }
185
186
    /**
187
     * {@inheritdoc}
188
     */
189 45
    public function resolve(bool $new = false)
190
    {
191 45
        $concrete = $this->concrete;
192
193 45
        if ($this->isShared() && $this->resolved !== null && $new === false) {
194 9
            return $this->resolved;
195
        }
196
197 45
        if (is_callable($concrete)) {
198 12
            $concrete = $this->resolveCallable($concrete);
199
        }
200
201 45
        if ($concrete instanceof RawArgumentInterface) {
202 3
            $this->resolved = $concrete->getValue();
203
204 3
            return $concrete->getValue();
205
        }
206
207 42
        if ($concrete instanceof ClassNameInterface) {
208 6
            $concrete = $concrete->getClassName();
209
        }
210
211 42
        if (is_string($concrete) && class_exists($concrete)) {
212 33
            $concrete = $this->resolveClass($concrete);
213
        }
214
215 42
        if (is_object($concrete)) {
216 39
            $concrete = $this->invokeMethods($concrete);
217
        }
218
219 42
        if (is_string($concrete) && $this->getContainer()->has($concrete)) {
220
            $concrete = $this->getContainer()->get($concrete);
221 42
        }
222
223
        $this->resolved = $concrete;
224
225
        return $concrete;
226
    }
227
228
    /**
229
     * Resolve a callable.
230
     *
231 12
     * @param callable $concrete
232
     *
233 12
     * @return mixed
234
     */
235 12
    protected function resolveCallable(callable $concrete)
236
    {
237
        $resolved = $this->resolveArguments($this->arguments);
238
239
        return call_user_func_array($concrete, $resolved);
240
    }
241
242
    /**
243
     * Resolve a class.
244
     *
245
     * @param string $concrete
246
     *
247 33
     * @return object
248
     *
249 33
     * @throws ReflectionException
250 33
     */
251
    protected function resolveClass(string $concrete)
252 33
    {
253
        $resolved   = $this->resolveArguments($this->arguments);
254
        $reflection = new ReflectionClass($concrete);
255
256
        return $reflection->newInstanceArgs($resolved);
257
    }
258
259
    /**
260
     * Invoke methods on resolved instance.
261
     *
262 39
     * @param object $instance
263
     *
264 39
     * @return object
265 3
     */
266
    protected function invokeMethods($instance)
267
    {
268 3
        foreach ($this->methods as $method) {
269 3
            $args = $this->resolveArguments($method['arguments']);
270
271
            /** @var callable $callable */
272 39
            $callable = [$instance, $method['method']];
273
            call_user_func_array($callable, $args);
274
        }
275
276
        return $instance;
277
    }
278
}
279