Completed
Pull Request — master (#126)
by Phil
11:02
created

Definition::resolve()   D

Complexity

Conditions 10
Paths 19

Size

Total Lines 34
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 34
rs 4.8196
c 0
b 0
f 0
cc 10
eloc 17
nc 19
nop 1

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
11
class Definition implements ArgumentResolverInterface, DefinitionInterface
12
{
13
    use ArgumentResolverTrait;
14
    use ContainerAwareTrait;
15
16
    /**
17
     * @var string
18
     */
19
    protected $alias;
20
21
    /**
22
     * @var mixed
23
     */
24
    protected $concrete;
25
26
    /**
27
     * @var boolean
28
     */
29
    protected $shared = false;
30
31
    /**
32
     * @var array
33
     */
34
    protected $tags = [];
35
36
    /**
37
     * @var array
38
     */
39
    protected $arguments = [];
40
41
    /**
42
     * @var array
43
     */
44
    protected $methods = [];
45
46
    /**
47
     * @var mixed
48
     */
49
    protected $resolved;
50
51
    /**
52
     * Constructor.
53
     *
54
     * @param string $id
55
     * @param mixed  $concrete
56
     */
57
    public function __construct(string $id, $concrete)
58
    {
59
        $this->alias    = $id;
60
        $this->concrete = $concrete;
61
    }
62
63
    /**
64
     * {@inheritdoc}
65
     */
66
    public function addTag(string $tag): DefinitionInterface
67
    {
68
        $this->tags[] = $tag;
69
70
        return $this;
71
    }
72
73
    /**
74
     * {@inheritdoc}
75
     */
76
    public function hasTag(string $tag): bool
77
    {
78
        return in_array($tag, $this->tags);
79
    }
80
81
    /**
82
     * {@inheritdoc}
83
     */
84
    public function setAlias(string $id): DefinitionInterface
85
    {
86
        $this->alias = $id;
87
88
        return $this;
89
    }
90
91
    /**
92
     * {@inheritdoc}
93
     */
94
    public function getAlias(): string
95
    {
96
        return $this->alias;
97
    }
98
99
    /**
100
     * {@inheritdoc}
101
     */
102
    public function setShared(bool $shared): DefinitionInterface
103
    {
104
        $this->shared = $shared;
105
106
        return $this;
107
    }
108
109
    /**
110
     * {@inheritdoc}
111
     */
112
    public function isShared(): bool
113
    {
114
        return $this->shared;
115
    }
116
117
    /**
118
     * {@inheritdoc}
119
     */
120
    public function addArgument($arg): DefinitionInterface
121
    {
122
        $this->arguments[] = $arg;
123
124
        return $this;
125
    }
126
127
    /**
128
     * {@inheritdoc}
129
     */
130
    public function addArguments(array $args): DefinitionInterface
131
    {
132
        foreach ($args as $arg) {
133
            $this->addArgument($arg);
134
        }
135
136
        return $this;
137
    }
138
139
    /**
140
     * {@inheritdoc}
141
     */
142
    public function addMethodCall(string $method, array $args = []): DefinitionInterface
143
    {
144
        $this->methods[] = [
145
            'method'    => $method,
146
            'arguments' => $args
147
        ];
148
149
        return $this;
150
    }
151
152
    /**
153
     * {@inheritdoc}
154
     */
155
    public function addMethodCalls(array $methods = []): DefinitionInterface
156
    {
157
        foreach ($methods as $method => $args) {
158
            $this->addMethodCall($method, $args);
159
        }
160
161
        return $this;
162
    }
163
164
    /**
165
     * {@inheritdoc}
166
     */
167
    public function resolve(bool $new = false)
168
    {
169
        $concrete = $this->concrete;
170
171
        if ($this->isShared() && ! is_null($this->resolved) && $new === false) {
172
            return $this->resolved;
173
        }
174
175
        if (is_callable($concrete)) {
176
            $concrete = $this->resolveCallable($concrete);
177
        }
178
179
        if ($concrete instanceof RawArgumentInterface) {
180
            $this->resolved = $concrete->getValue();
181
182
            return $concrete->getValue();
183
        }
184
185
        if ($concrete instanceof ClassNameInterface) {
186
            $concrete = $concrete->getValue();
187
        }
188
189
        if (is_string($concrete) && class_exists($concrete)) {
190
            $concrete = $this->resolveClass($concrete);
191
        }
192
193
        if (is_object($concrete)) {
194
            $concrete = $this->invokeMethods($concrete);
195
        }
196
197
        $this->resolved = $concrete;
198
199
        return $concrete;
200
    }
201
202
    /**
203
     * Resolve a callable.
204
     *
205
     * @param callable $concrete
206
     *
207
     * @return mixed
208
     */
209
    protected function resolveCallable(callable $concrete)
210
    {
211
        $resolved = $this->resolveArguments($this->arguments);
212
213
        return call_user_func_array($concrete, $resolved);
214
    }
215
216
    /**
217
     * Resolve a class.
218
     *
219
     * @param string $concrete
220
     * @param array  $args
0 ignored issues
show
Bug introduced by
There is no parameter named $args. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
221
     *
222
     * @return object
223
     */
224
    protected function resolveClass(string $concrete)
225
    {
226
        $resolved   = $this->resolveArguments($this->arguments);
227
        $reflection = new ReflectionClass($concrete);
228
229
        return $reflection->newInstanceArgs($resolved);
230
    }
231
232
    /**
233
     * Invoke methods on resolved instance.
234
     *
235
     * @param object $instance
236
     *
237
     * @return object
238
     */
239
    protected function invokeMethods($instance)
240
    {
241
        foreach ($this->methods as $method) {
242
            $args = $this->resolveArguments($method['arguments']);
243
            call_user_func_array([$instance, $method['method']], $args);
244
        }
245
246
        return $instance;
247
    }
248
}
249