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

Dependencies   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 77
Duplicated Lines 0 %

Test Coverage

Coverage 97.73%

Importance

Changes 0
Metric Value
dl 0
loc 77
ccs 43
cts 44
cp 0.9773
rs 10
c 0
b 0
f 0
wmc 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 12 1
A assertNoCircularDependency() 0 20 3
A build() 0 3 1
A lazy() 0 19 4
A bind() 0 10 1
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