-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathRender.php
More file actions
106 lines (94 loc) · 3.05 KB
/
Render.php
File metadata and controls
106 lines (94 loc) · 3.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
<?php
declare(strict_types = 1);
namespace Innmind\ObjectGraph;
use Innmind\Filesystem\File\Content;
use Innmind\Graphviz;
use Innmind\Colour\RGBA;
use Innmind\Immutable\Str;
/**
* @psalm-immutable
*/
final class Render
{
private RewriteLocation $rewriteLocation;
private Graphviz\Graph\Rankdir $direction;
private function __construct(
RewriteLocation $rewriteLocation,
Graphviz\Graph\Rankdir $direction,
) {
$this->rewriteLocation = $rewriteLocation;
$this->direction = $direction;
}
public function __invoke(Graph $graph): Content
{
$graphviz = Graphviz\Graph::directed('G', $this->direction)->add(
$this
->render($graph->root())
->shaped(
Graphviz\Node\Shape::hexagon()->fillWithColor(RGBA::of('#0f0')),
),
);
$graphviz = $graph
->nodes()
->remove($graph->root())
->map($this->render(...))
->reduce(
$graphviz,
static fn(Graphviz\Graph $graph, $node) => $graph->add($node),
);
return Graphviz\Layout\Dot::of()($graphviz);
}
/**
* @psalm-pure
*/
public static function of(?RewriteLocation $rewriteLocation = null): self
{
return new self(
$rewriteLocation ?? new RewriteLocation\NoOp,
Graphviz\Graph\Rankdir::leftToRight,
);
}
public function fromTopToBottom(): self
{
return new self($this->rewriteLocation, Graphviz\Graph\Rankdir::topToBottom);
}
private function render(Node $node): Graphviz\Node
{
/** @psalm-suppress ArgumentTypeCoercion As a class name can't be empty */
$render = Graphviz\Node::of(self::name($node->reference()))
->displayAs(
Str::of($node->class()->toString())
->replace("\x00", '') // remove the invisible character used in the name of anonymous classes
->replace('\\', '\\\\')
->toString(),
);
$render = $node
->location()
->map(fn($node) => ($this->rewriteLocation)($node))
->match(
static fn($location) => $render->target($location),
static fn() => $render,
);
if ($node->dependency()) {
$render = $render->shaped(
Graphviz\Node\Shape::box()->fillWithColor(RGBA::of('#ffb600')),
);
}
return $node
->relations()
->reduce(
$render,
static fn(Graphviz\Node $render, $relation) => $render->linkedTo(
self::name($relation->reference()),
static fn($edge) => $edge->displayAs($relation->property()->toString()),
),
);
}
/**
* @psalm-pure
*/
private static function name(Node\Reference $reference): Graphviz\Node\Name
{
return Graphviz\Node\Name::of('object_'.$reference->toString());
}
}