Visualize::linkNodes()   A
last analyzed

Complexity

Conditions 3
Paths 1

Size

Total Lines 71
Code Lines 44

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 50
CRAP Score 3.0005

Importance

Changes 0
Metric Value
cc 3
eloc 44
nc 1
nop 1
dl 0
loc 71
ccs 50
cts 52
cp 0.9615
crap 3.0005
rs 9.216
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
declare(strict_types = 1);
3
4
namespace Innmind\Compose;
5
6
use Innmind\Compose\{
7
    Arguments as Args,
8
    Definition\Argument as Arg,
9
    Definition\Name,
10
    Definition\Service,
11
    Definition\Service\Constructor,
12
    Definition\Service\Argument,
13
    Definition\Service\Argument\HoldReference,
14
    Definition\Service\Argument\HoldReferences,
15
    Visualization\Graph\Dependency,
16
    Visualization\Graph\Arguments,
17
    Visualization\Node\Element
18
};
19
use Innmind\Graphviz\{
20
    Graph,
21
    Node\Node
22
};
23
use Innmind\Immutable\{
24
    MapInterface,
25
    Set,
26
    Str,
27
    Map
28
};
29
30
final class Visualize
31
{
32 1
    public function __invoke(Services $services): Graph
33
    {
34
        $graph = $this
35 1
            ->loadClusters($services->dependencies())
36 1
            ->reduce(
37 1
                Graph\Graph::directed('G', Graph\Rankdir::leftToRight()),
38 1
                static function(Graph $graph, Graph $cluster): Graph {
39 1
                    return $graph->cluster($cluster);
40 1
                }
41
            )
42 1
            ->cluster(new Arguments($services->arguments()));
43
44 1
        $nodes = $this->buildNodes($services);
45 1
        $this->linkNodes($nodes);
46
47 1
        $graph = $nodes->reduce(
48 1
            $graph,
49 1
            static function(Graph $graph, string $name, array $pair): Graph {
50 1
                return $graph->add($pair[0]);
51 1
            }
52
        );
53
54 1
        return $this->linkDefaults($graph, $services->arguments(), $nodes);
55
    }
56
57 1
    private function loadClusters(Dependencies $dependencies): Set
58
    {
59 1
        return $dependencies->exposed()->reduce(
60 1
            Set::of(Graph::class),
61 1
            static function(Set $clusters, Name $dependency, MapInterface $services): Set {
62 1
                return $clusters->add(new Dependency($dependency, $services));
63 1
            }
64
        );
65
    }
66
67 1
    private function buildNodes(Services $services): Map
68
    {
69
        return $services
70 1
            ->all()
71 1
            ->filter(static function(Service $service): bool {
72 1
                return !$service->decorates();
73 1
            })
74 1
            ->reduce(
75 1
                new Map('string', 'array'),
76 1
                static function(Map $nodes, Service $service): Map {
77 1
                    $node = Element::service($service);
78
79 1
                    return $nodes->put(
80 1
                        (string) $node->name(),
81 1
                        [$node, $service]
82
                    );
83 1
                }
84
            );
85
    }
86
87 1
    private function linkNodes(Map $nodes): void
88
    {
89
        $nodes
90 1
            ->values()
91 1
            ->filter(static function(array $pair): bool {
92
                //do not try to link nodes for services that do not depend on
93
                //other services
94 1
                return $pair[1]
95 1
                    ->arguments()
96 1
                    ->filter(static function(Argument $argument): bool {
97 1
                        return $argument instanceof HoldReference;
98 1
                    })
99 1
                    ->size() > 0;
100 1
            })
101 1
            ->foreach(static function(array $pair) use ($nodes): void {
102 1
                $pair[1]
103 1
                    ->arguments()
104 1
                    ->filter(static function(Argument $argument): bool {
105 1
                        return $argument instanceof HoldReference;
106 1
                    })
107 1
                    ->foreach(static function(HoldReference $argument) use ($pair, $nodes): void {
108 1
                        $name = (string) Element::build($argument->reference())->name();
109
110
                        //an argument or a dependency
111 1
                        if (!$nodes->contains($name)) {
112 1
                            $pair[0]->linkedTo(Node::named($name));
113
114 1
                            return;
115
                        }
116
117 1
                        $pair[0]->linkedTo(
118 1
                            $nodes->get($name)[0]
119
                        );
120 1
                    });
121 1
            });
122
        $nodes
123 1
            ->values()
124 1
            ->filter(static function(array $pair): bool {
125
                //do not try to link nodes for services that do not depend on
126
                //other services
127 1
                return $pair[1]
128 1
                    ->arguments()
129 1
                    ->filter(static function(Argument $argument): bool {
130 1
                        return $argument instanceof HoldReferences;
131 1
                    })
132 1
                    ->size() > 0;
133 1
            })
134 1
            ->foreach(static function(array $pair) use ($nodes): void {
135 1
                $pair[1]
136 1
                    ->arguments()
137 1
                    ->filter(static function(Argument $argument): bool {
138 1
                        return $argument instanceof HoldReferences;
139 1
                    })
140 1
                    ->reduce(
141 1
                        Set::of(Name::class),
142 1
                        static function(Set $names, HoldReferences $argument): Set {
143 1
                            return $names->merge($argument->references());
144 1
                        }
145
                    )
146 1
                    ->foreach(static function(Name $name) use ($pair, $nodes): void {
147 1
                        $name = (string) Element::build($name)->name();
148
149
                        //an argument or a dependency
150 1
                        if (!$nodes->contains($name)) {
151
                            $pair[0]->linkedTo(Node::named($name));
152
153
                            return;
154
                        }
155
156 1
                        $pair[0]->linkedTo(
157 1
                            $nodes->get($name)[0]
158
                        );
159 1
                    });
160 1
            });
161 1
    }
162
163 1
    private function linkDefaults(Graph $graph, Args $arguments, Map $nodes): Graph
164
    {
165
        return $arguments
166 1
            ->all()
167 1
            ->filter(static function(Arg $argument): bool {
168 1
                return $argument->hasDefault();
169 1
            })
170 1
            ->reduce(
171 1
                $graph,
172 1
                static function(Graph $graph, Arg $argument) use ($nodes): Graph {
173 1
                    $node = Element::build($argument->name());
174 1
                    $default = Element::build($argument->default());
175 1
                    $default = $nodes->get((string) $default->name())[0];
176 1
                    $edge = $node->linkedTo($default);
177
                    $edge
178 1
                        ->dotted()
179 1
                        ->displayAs('defaults to');
180
181 1
                    return $graph->add($node);
182 1
                }
183
            );
184
    }
185
}
186