Completed
Push — develop ( 15ec3c...8b62a8 )
by Baptiste
02:19
created

Dependency::compile()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 0
dl 0
loc 6
ccs 5
cts 5
cp 1
crap 1
rs 9.4285
c 0
b 0
f 0
1
<?php
2
declare(strict_types = 1);
3
4
namespace Innmind\Compose\Definition;
5
6
use Innmind\Compose\{
7
    Definition\Dependency\Parameter,
8
    Definition\Service\Argument,
9
    Services,
10
    Lazy,
11
    Exception\ReferenceNotFound,
12
    Exception\ArgumentNotExtractable,
13
    Compilation\Dependency as CompiledDependency
14
};
15
use Innmind\Immutable\{
16
    Set,
17
    MapInterface,
18
    Map,
19
    StreamInterface
20
};
21
22
final class Dependency
23
{
24
    private $name;
25
    private $services;
26
    private $parameters;
27
28 62
    public function __construct(
29
        Name $name,
30
        Services $services,
31
        Parameter ...$parameters
32
    ) {
33 62
        $this->name = $name;
34 62
        $this->services = $services;
35 62
        $this->parameters = Set::of(Parameter::class, ...$parameters);
36 62
    }
37
38 37
    public function name(): Name
39
    {
40 37
        return $this->name;
41
    }
42
43 8
    public function bind(Services $services): self
44
    {
45
        $parameters = $this
46 8
            ->parameters
47 8
            ->reduce(
48 8
                new Map('string', 'mixed'),
49 8
                static function(Map $parameters, Parameter $parameter) use ($services): Map {
50 8
                    return $parameters->put(
51 8
                        (string) $parameter->name(),
52 8
                        $parameter->resolve($services)
53
                    );
54 8
                }
55
            );
56
57 8
        $self = clone $this;
58 8
        $self->services = $self->services->inject($parameters);
59
60 8
        return $self;
61
    }
62
63 21
    public function lazy(Name $name): Lazy
64
    {
65 21
        if (!$this->has($name)) {
66 7
            throw new ReferenceNotFound((string) $name);
67
        }
68
69 14
        return Lazy::service(
70 14
            $name,
71 14
            $this->services
72
        );
73
    }
74
75 5
    public function build(Name $name): object
76
    {
77 5
        return $this->lazy($name)->load();
78
    }
79
80 47
    public function has(Name $name): bool
81
    {
82 47
        if (!$this->services->has($name)) {
83 6
            return false;
84
        }
85
86 42
        $service = $this->services->get($name);
87
88 42
        if (!$service->exposed() || !$service->isExposedAs($name)) {
89 12
            return false;
90
        }
91
92 31
        return true;
93
    }
94
95 5
    public function dependsOn(self $other): bool
96
    {
97 5
        return $this->parameters->reduce(
98 5
            false,
99 5
            function(bool $dependsOn, Parameter $parameter) use ($other): bool {
100 3
                return $dependsOn || $parameter->refersTo($other);
101 5
            }
102
        );
103
    }
104
105 13
    public function decorate(
106
        Name $decorator,
107
        Name $decorated,
108
        Name $newName = null
109
    ): Service {
110 13
        if (!$this->has($decorator)) {
111 4
            throw new ReferenceNotFound((string) $decorator);
112
        }
113
114 9
        $service = $this->services->get($decorator);
115
116 9
        return $service->tunnel($this->name, $decorated, $newName);
117
    }
118
119
    /**
120
     * @param StreamInterface<mixed> $arguments
121
     *
122
     * @return StreamInterface<mixed>
123
     */
124 11
    public function extract(
125
        Name $name,
126
        StreamInterface $arguments,
127
        Argument $argument
128
    ): StreamInterface {
129 11
        if (!$this->has($name)) {
130 5
            throw new ReferenceNotFound((string) $name);
131
        }
132
133 6
        $service = $this->services->get($name);
134
135
        if (
136 6
            !$service->decorates() ||
137 6
            !$service->arguments()->contains($argument)
138
        ) {
139 2
            throw new ArgumentNotExtractable;
140
        }
141
142 4
        return $argument->resolve(
143 4
            $arguments,
144 4
            $this->services
145
        );
146
    }
147
148
    /**
149
     * The list of exposed services name with their constructor
150
     *
151
     * @return MapInterface<Name, Constructor>
152
     */
153 3
    public function exposed(): MapInterface
154
    {
155 3
        return $this->services->exposed();
156
    }
157
158 6
    public function compile(): CompiledDependency
159
    {
160 6
        return new CompiledDependency(
161 6
            $this->name,
162 6
            $this->services,
163 6
            ...$this->parameters
164
        );
165
    }
166
}
167