Passed
Push — master ( cf7539...f211e4 )
by n
03:42
created

Invoker::complement()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 31
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 5

Importance

Changes 0
Metric Value
eloc 19
c 0
b 0
f 0
dl 0
loc 31
ccs 19
cts 19
cp 1
rs 9.3222
cc 5
nc 5
nop 2
crap 5
1
<?php
2
declare(strict_types=1);
3
4
namespace N1215\CakeCandle\Invoker;
5
6
use N1215\CakeCandle\Invoker\Exceptions\InsufficientArgumentsException;
7
use N1215\CakeCandle\Invoker\Exceptions\ReflectionFailedException;
8
use N1215\CakeCandle\Reflection\ReflectionCallable;
9
use Psr\Container\ContainerInterface;
10
use ReflectionException;
11
12
final class Invoker implements InvokerInterface
13
{
14
    /**
15
     * @var ContainerInterface
16
     */
17
    private $container;
18
19
    /**
20
     * @param ContainerInterface $container
21
     */
22 19
    public function __construct(ContainerInterface $container)
23
    {
24 19
        $this->container = $container;
25 19
    }
26
27
    /**
28
     * @inheritdoc
29
     */
30 4
    public function invoke(callable $callable, array $args = [])
31
    {
32 4
        $complementedArguments = $this->complement($callable, $args);
33 1
        return $callable(...$complementedArguments);
34
    }
35
36
    /**
37
     * @inheritDoc
38
     */
39 6
    public function complement(callable $callable, array $args = []): array
40
    {
41 6
        $originalArguments = array_values($args);
42
        try {
43 6
            $reflectionCallable = new ReflectionCallable($callable);
44 1
        } catch (ReflectionException $e) {
45 1
            throw new ReflectionFailedException('failed to get reflection of the callable', 0, $e);
46
        }
47
48 5
        $parameters = $reflectionCallable->getParameters();
49
50 5
        $complementedArguments = [];
51 5
        foreach ($parameters as $parameter) {
52 5
            $class = $parameter->getClass();
53 5
            if ($class !== null) {
54 5
                $complementedArguments[] = $this->container->get($class->getName());
55 5
                continue;
56
            }
57
58 5
            if (count($originalArguments) === 0) {
59 1
                $position = $parameter->getPosition() + 1;
60 1
                $name = $parameter->getName();
61 1
                throw new InsufficientArgumentsException(
62 1
                    "Unable to fill the argument {$position} `{$name}`."
63
                );
64
            }
65
66 5
            $complementedArguments[] = array_shift($originalArguments);
67
        }
68
69 3
        return $complementedArguments;
70
    }
71
}
72