Passed
Pull Request — 1.x (#12)
by
unknown
14:23
created

MermaidRenderer   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 88
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 13
eloc 48
c 3
b 0
f 0
dl 0
loc 88
rs 10

1 Method

Rating   Name   Duplication   Size   Complexity  
C render() 0 80 13
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Cycle\Schema\Renderer\MermaidRenderer;
6
7
use Cycle\ORM\Relation;
8
use Cycle\ORM\SchemaInterface;
9
use Cycle\Schema\Renderer\MermaidRenderer\Entity\EntityArrow;
10
use Cycle\Schema\Renderer\MermaidRenderer\Entity\EntityTable;
11
use Cycle\Schema\Renderer\MermaidRenderer\Exception\RelationNotFoundException;
12
use Cycle\Schema\Renderer\MermaidRenderer\Schema\ClassDiagram;
13
use Cycle\Schema\Renderer\SchemaRenderer;
14
15
final class MermaidRenderer implements SchemaRenderer
16
{
17
    private const METHOD_FORMAT = '%s: %s';
18
    private const REGEX = "/^[a-zA-Z_]+$/";
19
20
    /**
21
     * @throws RelationNotFoundException
22
     */
23
    public function render(array $schema): string
24
    {
25
        $class = new ClassDiagram();
26
        $relationMapper = new RelationMapper();
27
28
        foreach ($schema as $key => $value) {
29
            if (!isset($value[SchemaInterface::COLUMNS]) || !preg_match(self::REGEX, $key)) {
30
                continue;
31
            }
32
33
            $role = $value[SchemaInterface::ROLE] ?? '';
34
35
            if (!preg_match(self::REGEX, $role)) {
36
                $role = $key;
37
            }
38
39
            $table = new EntityTable($role);
40
            $arrow = new EntityArrow();
41
42
            foreach ($value[SchemaInterface::COLUMNS] as $column) {
43
                $table->addRow($value[SchemaInterface::TYPECAST][$column] ?? 'string', $column);
44
            }
45
46
            foreach ($value[SchemaInterface::RELATIONS] ?? [] as $relationKey => $relation) {
47
                if (!isset($relation[Relation::TARGET], $relation[Relation::SCHEMA])) {
48
                    continue;
49
                }
50
51
                $target = $relation[Relation::TARGET];
52
                $isNullable = $relation[Relation::SCHEMA][Relation::NULLABLE] ?? false;
53
54
                $mappedRelation = $relationMapper->mapWithNode($relation[Relation::TYPE], $isNullable);
55
56
                switch ($relation[Relation::TYPE]) {
57
                    case Relation::MANY_TO_MANY:
58
                        $throughEntity = $relation[Relation::SCHEMA][Relation::THROUGH_ENTITY] ?? null;
59
60
                        if ($throughEntity) {
61
                            $table->addMethod($relationKey, sprintf(self::METHOD_FORMAT, $mappedRelation[0], $target));
62
63
                            // tag --* post : posts
64
                            $arrow->addArrow($role, $target, $relationKey, $mappedRelation[1]);
65
                            // postTag ..> tag : tag.posts
66
                            $arrow->addArrow($throughEntity, $role, "$role.$relationKey", '..>');
67
                            // postTag ..> post : tag.posts
68
                            $arrow->addArrow($throughEntity, $target, "$role.$relationKey", '..>');
69
                        }
70
                        break;
71
                    case Relation::EMBEDDED:
72
                        // explode string like user:credentials
73
                        $methodTarget = explode(':', $target);
74
75
                        $table->addMethod(
76
                            $methodTarget[1] ?? $target,
77
                            sprintf(self::METHOD_FORMAT, $mappedRelation[0], $relationKey)
78
                        );
79
80
                        $arrowTarget = str_replace(':', '&#58', $target);
81
82
                        $arrow->addArrow($role, $relationKey, $arrowTarget, $mappedRelation[1]);
83
                        break;
84
                    default:
85
                        $table->addMethod($relationKey, sprintf(self::METHOD_FORMAT, $mappedRelation[0], $target));
86
                        $arrow->addArrow($role, $target, $relationKey, $mappedRelation[1]);
87
                }
88
            }
89
90
            foreach ($value[SchemaInterface::CHILDREN] ?? [] as $children) {
91
                $arrow->addArrow($role, $children, 'STI', '--|>');
92
            }
93
94
            if (isset($value[SchemaInterface::PARENT])) {
95
                $arrow->addArrow($value[SchemaInterface::PARENT], $role, 'JTI', '--|>');
96
            }
97
98
            $class->addEntity($table);
99
            $class->addEntity($arrow);
100
        }
101
102
        return (string)$class;
103
    }
104
}
105