Completed
Push — develop ( fc6f83...efe27a )
by Baptiste
02:01
created

Dependencies::lazy()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 13
nc 4
nop 1
dl 0
loc 19
ccs 11
cts 11
cp 1
crap 4
rs 9.2
c 0
b 0
f 0
1
<?php
2
declare(strict_types = 1);
3
4
namespace Innmind\Compose;
5
6
use Innmind\Compose\{
7
    Definition\Dependency,
8
    Definition\Name,
9
    Exception\ReferenceNotFound,
10
    Exception\NameNotNamespaced,
11
    Exception\CircularDependency
12
};
13
use Innmind\Immutable\{
14
    Sequence,
15
    Map
16
};
17
18
final class Dependencies
19
{
20
    private $dependencies;
21
22 159
    public function __construct(Dependency ...$dependencies)
23
    {
24 159
        $this->dependencies = Sequence::of(...$dependencies)->reduce(
25 159
            new Map('string', Dependency::class),
26 159
            static function(Map $dependencies, Dependency $dependency): Map {
27 14
                return $dependencies->put(
28 14
                    (string) $dependency->name(),
29 14
                    $dependency
30
                );
31 159
            }
32
        );
33 159
        $this->assertNoCircularDependency();
34 159
    }
35
36 31
    public function bind(Services $services): self
37
    {
38 31
        $self = clone $this;
39 31
        $self->dependencies = $self
40 31
            ->dependencies
41 31
            ->map(static function(string $name, Dependency $dependency) use ($services): Dependency {
42 2
                return $dependency->bind($services);
43 31
            });
44
45 31
        return $self;
46
    }
47
48 24
    public function lazy(Name $name): Lazy
49
    {
50
        try {
51 24
            $root = $name->root();
52 12
        } catch (NameNotNamespaced $e) {
53 12
            throw new ReferenceNotFound((string) $name);
54
        }
55
56 14
        if (!$this->dependencies->contains((string) $root)) {
57 5
            throw new ReferenceNotFound((string) $name);
58
        }
59
60
        try {
61
            return $this
62 9
                ->dependencies
63 9
                ->get((string) $root)
64 9
                ->lazy($name->withoutRoot());
65 3
        } catch (ReferenceNotFound $e) {
66 3
            throw new ReferenceNotFound((string) $name, 0, $e);
67
        }
68
    }
69
70 8
    public function build(Name $name): object
71
    {
72 8
        return $this->lazy($name)->load();
73
    }
74
75
    private function assertNoCircularDependency(): void
76
    {
77 159
        $this->dependencies->foreach(function(string $name, Dependency $dependency): void {
78
            $this
79 14
                ->dependencies
80 14
                ->remove($name)
81 14
                ->foreach(static function(string $name, Dependency $other) use ($dependency): void {
82 3
                    if (!$dependency->dependsOn($other)) {
83 3
                        return;
84
                    }
85
86 1
                    if (!$other->dependsOn($dependency)) {
87
                        return;
88
                    }
89
90 1
                    throw new CircularDependency(sprintf(
91 1
                        '%s -> %s -> %s',
92 1
                        $dependency->name(),
93 1
                        $other->name(),
94 1
                        $dependency->name()
95
                    ));
96 14
                });
97 159
        });
98 159
    }
99
}
100