Completed
Push — develop ( 523088...d9cee5 )
by Baptiste
01:42
created

Definitions::fetchArgumentValue()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 16
ccs 6
cts 6
cp 1
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 6
nc 3
nop 1
crap 3
1
<?php
2
declare(strict_types = 1);
3
4
namespace Innmind\Compose;
5
6
use Innmind\Compose\{
7
    Definition\Name,
8
    Definition\Service,
9
    Definition\Service\Argument,
10
    Exception\ArgumentNotProvided
11
};
12
use Innmind\Immutable\{
13
    Sequence,
14
    MapInterface,
15
    Map
16
};
17
18
final class Definitions
19
{
20
    private $definitions;
21
    private $arguments;
22
23 3
    public function __construct(Arguments $arguments, Service ...$definitions)
24
    {
25 3
        $this->arguments = $arguments;
26 3
        $this->definitions = Sequence::of(...$definitions)->reduce(
27 3
            new Map('string', Service::class),
28 3
            static function(Map $definitions, Service $definition): Map {
29 3
                return $definitions->put(
30 3
                    (string) $definition->name(),
31 3
                    $definition
32
                );
33 3
            }
34
        );
35 3
    }
36
37
    /**
38
     * @param MapInterface<string, mixed> $arguments
39
     */
40 2
    public function inject(MapInterface $arguments): self
41
    {
42 2
        $self = clone $this;
43 2
        $self->arguments = $self->arguments->bind($arguments);
44
45 2
        return $self;
46
    }
47
48 1
    public function build(Name $name): object
49
    {
50 1
        $definition = $this->get($name);
51 1
        $arguments = $this->buildArguments($definition);
52 1
        $construct = $definition->constructor();
53
54 1
        return $construct(...$arguments);
55
    }
56
57 2
    public function arguments(): Arguments
58
    {
59 2
        return $this->arguments;
60
    }
61
62 1
    public function has(Name $name): bool
63
    {
64 1
        return $this->definitions->contains((string) $name);
65
    }
66
67 2
    public function get(Name $name): Service
68
    {
69 2
        return $this->definitions->get((string) $name);
70
    }
71
72 1
    public function buildArguments(Service $service): Sequence
73
    {
74
        return $service
75 1
            ->arguments()
76 1
            ->reduce(
77 1
                new Sequence,
78 1
                function(Sequence $arguments, Argument $argument): Sequence {
79
                    // @todo: handle the decoration
80 1
                    $value = $this->fetchArgumentValue($argument);
81
82 1
                    if ($argument->toUnwind()) {
83 1
                        return $arguments->append(new Sequence(...$value ?? []));
84
                    }
85
86 1
                    return $arguments->add($value);
87 1
                }
88
            );
89
    }
90
91 1
    public function fetchArgumentValue(Argument $argument)
92
    {
93
        try {
94 1
            return $this->arguments->get($argument->reference());
95 1
        } catch (ArgumentNotProvided $e) {
96
            //pass
97
        }
98
99 1
        if ($e->argument()->hasDefault()) {
100 1
            return $this->build($e->argument()->default());
101
        }
102
103
        //null as the argument must be optional here, requirement as been
104
        //checked earlier
105
106 1
        return null;
107
    }
108
}
109