Passed
Push — master ( b93948...5cdbe6 )
by Alexey
03:54
created

ArgumentResolver::resolve()   B

Complexity

Conditions 4
Paths 1

Size

Total Lines 37
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 4

Importance

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