Definition::resolveNew()   C
last analyzed

Complexity

Conditions 12
Paths 102

Size

Total Lines 43
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 23
CRAP Score 12

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 23
c 1
b 0
f 0
dl 0
loc 43
ccs 23
cts 23
cp 1
rs 6.95
cc 12
nc 102
nop 0
crap 12

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