ArgumentResolver::resolve()   B
last analyzed

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 42
    public function __construct(ContainerContract $container)
29
    {
30 42
        $this->container = $container;
31 42
    }
32
33
    /**
34
     * @inheritdoc
35
     */
36 33
    public function resolve(ReflectionFunctionAbstract $function, array $arguments = []): array
37
    {
38 33
        $parameters = $function->getParameters();
39
40
        // Use passed arguments in place of reflected parameters.
41 33
        $provided = array_intersect_key($arguments, $parameters);
42
43
        // Remaining parameters will be resolved by container.
44 33
        $remaining = array_diff_key($parameters, $arguments);
45 33
        $resolved = array_map(
46 33
            function (ReflectionParameter $parameter) use ($function) {
47
48
                // Recursively resolve function arguments.
49 24
                $class = $parameter->getClass();
50 24
                if ($class !== null && $this->container->has($class->getName())) {
51 20
                    return $this->container->get($class->getName());
52
                }
53
54
                // Use argument default value if possible.
55 7
                if ($parameter->isDefaultValueAvailable()) {
56 4
                    return $parameter->getDefaultValue();
57
                }
58
59
                // The argument can't be resolved by this resolver.
60 3
                throw new ArgumentResolverException($parameter, $function);
61
62 33
            },
63
            $remaining
64
        );
65
66 27
        $arguments = $provided + $resolved;
67
68
        // Sort combined result array by parameter indexes.
69 27
        ksort($arguments);
70
71 27
        return $arguments;
72
    }
73
}