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

Definition::resolveCallable()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 4
cts 4
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 2
crap 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
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 $arguments = [];
35
36
    /**
37
     * @var array
38
     */
39
    protected $methods = [];
40
41
    /**
42
     * @var mixed
43
     */
44
    protected $resolved;
45
46
    /**
47
     * Constructor.
48
     *
49
     * @param string $id
50
     * @param mixed  $concrete
51
     */
52 36
    public function __construct(string $id, $concrete)
53
    {
54 36
        $this->alias    = $id;
55 36
        $this->concrete = $concrete;
56 36
    }
57
58
    /**
59
     * {@inheritdoc}
60
     */
61 6
    public function setAlias(string $id): DefinitionInterface
62
    {
63 6
        $this->alias = $id;
64
65 6
        return $this;
66
    }
67
68
    /**
69
     * {@inheritdoc}
70
     */
71 3
    public function getAlias(): string
72
    {
73 3
        return $this->alias;
74
    }
75
76
    /**
77
     * {@inheritdoc}
78
     */
79 9
    public function setShared(bool $shared): DefinitionInterface
80
    {
81 9
        $this->shared = $shared;
82
83 9
        return $this;
84
    }
85
86
    /**
87
     * {@inheritdoc}
88
     */
89 30
    public function isShared(): bool
90
    {
91 30
        return $this->shared;
92
    }
93
94
    /**
95
     * {@inheritdoc}
96
     */
97 18
    public function addArgument($arg): DefinitionInterface
98
    {
99 18
        $this->arguments[] = $arg;
100
101 18
        return $this;
102
    }
103
104
    /**
105
     * {@inheritdoc}
106
     */
107 6
    public function addArguments(array $args): DefinitionInterface
108
    {
109 6
        foreach ($args as $arg) {
110 6
            $this->addArgument($arg);
111
        }
112
113 6
        return $this;
114
    }
115
116
    /**
117
     * {@inheritdoc}
118
     */
119 3
    public function addMethodCall(string $method, array $args = []): DefinitionInterface
120
    {
121 3
        $this->methods[] = [
122 3
            'method'    => $method,
123 3
            'arguments' => $args
124
        ];
125
126 3
        return $this;
127
    }
128
129
    /**
130
     * {@inheritdoc}
131
     */
132 3
    public function addMethodCalls(array $methods = []): DefinitionInterface
133
    {
134 3
        foreach ($methods as $method => $args) {
135 3
            $this->addMethodCall($method, $args);
136
        }
137
138 3
        return $this;
139
    }
140
141
    /**
142
     * {@inheritdoc}
143
     */
144 30
    public function resolve(array $args = [], bool $new = false)
145
    {
146 30
        $concrete = $this->concrete;
147
148 30
        if ($this->isShared() && ! is_null($this->resolved) && $new === false) {
149 3
            return $this->resolved;
150
        }
151
152 30
        if (is_callable($concrete)) {
153 15
            $concrete = $this->resolveCallable($concrete, $args);
154
        }
155
156 30
        if ($concrete instanceof RawArgumentInterface) {
157 3
            $this->resolved = $concrete->getValue();
158
159 3
            return $concrete->getValue();
160
        }
161
162 27
        if ($concrete instanceof ClassNameInterface) {
163 6
            $concrete = $concrete->getValue();
164
        }
165
166 27
        if (is_string($concrete) && class_exists($concrete)) {
167 15
            $concrete = $this->resolveClass($concrete, $args);
168
        }
169
170 27
        if (is_object($concrete)) {
171 21
            $concrete = $this->invokeMethods($concrete);
172
        }
173
174 27
        $this->resolved = $concrete;
175
176 27
        return $concrete;
177
    }
178
179
    /**
180
     * Resolve a callable.
181
     *
182
     * @param callable $concrete
183
     * @param array    $args
184
     *
185
     * @return mixed
186
     */
187 15
    protected function resolveCallable(callable $concrete, array $args = [])
188
    {
189 15
        $args     = (empty($args)) ? $this->arguments : $args;
190 15
        $resolved = $this->resolveArguments($args);
191
192 15
        return call_user_func_array($concrete, $resolved);
193
    }
194
195
    /**
196
     * Resolve a class.
197
     *
198
     * @param string $concrete
199
     * @param array  $args
200
     *
201
     * @return object
202
     */
203 15
    protected function resolveClass(string $concrete, array $args = [])
204
    {
205 15
        $args       = (empty($args)) ? $this->arguments : $args;
206 15
        $resolved   = $this->resolveArguments($args);
207 15
        $reflection = new ReflectionClass($concrete);
208
209 15
        return $reflection->newInstanceArgs($resolved);
210
    }
211
212
    /**
213
     * Invoke methods on resolved instance.
214
     *
215
     * @param object $instance
216
     *
217
     * @return object
218
     */
219 21
    protected function invokeMethods($instance)
220
    {
221 21
        foreach ($this->methods as $method) {
222 3
            $args = $this->resolveArguments($method['arguments']);
223 3
            call_user_func_array([$instance, $method['method']], $args);
224
        }
225
226 21
        return $instance;
227
    }
228
}
229