Passed
Push — master ( ba70cb...992fc1 )
by Sergei
21:39 queued 19:24
created

CallableDefinition::prepareClosure()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 5
nc 3
nop 2
dl 0
loc 11
ccs 6
cts 6
cp 1
crap 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Definitions;
6
7
use Closure;
8
use ReflectionException;
9
use ReflectionFunction;
10
use ReflectionMethod;
11
use Yiisoft\Definitions\Contract\DefinitionInterface;
12
use Yiisoft\Definitions\Contract\DependencyResolverInterface;
13
use Yiisoft\Definitions\Exception\NotInstantiableException;
14
use Yiisoft\Definitions\Infrastructure\DefinitionExtractor;
15
use Yiisoft\Definitions\Infrastructure\DefinitionResolver;
16
17
use function is_array;
18
use function is_object;
19
20
final class CallableDefinition implements DefinitionInterface
21
{
22
    /**
23
     * @var array|callable
24
     * @psalm-var callable|array{0:class-string,1:string}
25
     */
26
    private $callable;
27
28
    /**
29
     * @param array|callable $callable
30
     *
31
     * @psalm-param callable|array{0:class-string,1:string} $callable
32
     */
33 5
    public function __construct($callable)
34
    {
35 5
        $this->callable = $callable;
36 5
    }
37
38 5
    public function resolve(DependencyResolverInterface $dependencyResolver)
39
    {
40
        try {
41 5
            $reflection = new ReflectionFunction(
42 5
                $this->prepareClosure($this->callable, $dependencyResolver)
43
            );
44 1
        } catch (ReflectionException $e) {
45 1
            throw new NotInstantiableException(
46 1
                'Can not instantiate callable definition. Got ' . var_export($this->callable, true)
47
            );
48
        }
49
50 4
        $dependencies = DefinitionExtractor::getInstance()->fromFunction($reflection);
51 4
        $arguments = DefinitionResolver::resolveArray($dependencyResolver, $dependencies);
52
53 4
        return $reflection->invokeArgs($arguments);
54
    }
55
56
    /**
57
     * @param array|callable $callable
58
     *
59
     * @psalm-param callable|array{0:class-string,1:string} $callable
60
     */
61 5
    private function prepareClosure($callable, DependencyResolverInterface $dependencyResolver): Closure
62
    {
63 5
        if (is_array($callable) && !is_object($callable[0])) {
64 3
            $reflection = new ReflectionMethod($callable[0], $callable[1]);
65 2
            if (!$reflection->isStatic()) {
66
                /** @var mixed */
67 1
                $callable[0] = $dependencyResolver->resolve($callable[0]);
68
            }
69
        }
70
71 4
        return Closure::fromCallable($callable);
72
    }
73
}
74