Passed
Push — master ( d44e7d...fd48aa )
by Alexey
07:53
created

ArgumentResolver::createCallback()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 6
ccs 3
cts 3
cp 1
crap 1
rs 9.4285
c 0
b 0
f 0
1
<?php declare(strict_types = 1);
2
3
namespace Venta\Container;
4
5
use Closure;
6
use ReflectionFunctionAbstract;
7
use ReflectionParameter;
8
use Venta\Container\Exception\ArgumentResolverException;
9
use Venta\Contracts\Container\ArgumentResolver as ArgumentResolverContract;
10
use Venta\Contracts\Container\Container as ContainerContract;
11
12
/**
13
 * Class ArgumentResolver.
14
 *
15
 * @package Venta\Container
16
 */
17
final class ArgumentResolver implements ArgumentResolverContract
18
{
19
    /**
20
     * @var ContainerContract
21
     */
22
    private $container;
23
24
    /**
25
     * ArgumentResolver constructor.
26
     *
27
     * @param ContainerContract $container
28
     */
29 51
    public function __construct(ContainerContract $container)
30
    {
31 51
        $this->container = $container;
32 51
    }
33
34
    /**
35
     * @inheritDoc
36
     */
37 30
    public function createCallback(ReflectionFunctionAbstract $function): Closure
38
    {
39
        return function (array $arguments = []) use ($function) {
40 30
            return $this->resolve($function, $arguments);
41 30
        };
42
    }
43
44
    /**
45
     * @inheritdoc
46
     */
47 38
    public function resolve(ReflectionFunctionAbstract $function, array $arguments = []): array
48
    {
49 38
        $parameters = $function->getParameters();
50
51
        // Use passed arguments in place of reflected parameters.
52 38
        $provided = array_intersect_key($arguments, $parameters);
53
54
        // Remaining parameters will be resolved by container.
55 38
        $remaining = array_diff_key($parameters, $arguments);
56 38
        $resolved = array_map(
57 38
            function (ReflectionParameter $parameter) use ($function) {
58
59
                // Recursively resolve function arguments.
60 26
                $class = $parameter->getClass();
61 26
                if ($class !== null && $this->container->has($class->getName())) {
62 22
                    return $this->container->get($class->getName());
63
                }
64
65
                // Use argument default value if possible.
66 5
                if ($parameter->isDefaultValueAvailable()) {
67 2
                    return $parameter->getDefaultValue();
68
                }
69
70
                // The argument can't be resolved by this resolver.
71 3
                throw new ArgumentResolverException($parameter, $function);
72
73 38
            },
74
            $remaining
75
        );
76
77 32
        $arguments = $provided + $resolved;
78
79
        // Sort combined result array by parameter indexes.
80 32
        ksort($arguments);
81
82 32
        return $arguments;
83
    }
84
}