Issues (19)

src/GraphBuilder.php (5 issues)

1
<?php
2
3
namespace BeyondCode\ErdGenerator;
4
5
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
6
use phpDocumentor\GraphViz\Graph;
7
use Illuminate\Support\Collection;
8
use phpDocumentor\GraphViz\Node;
9
use \Illuminate\Database\Eloquent\Model as EloquentModel;
0 ignored issues
show
The type \Illuminate\Database\Eloquent\Model was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
10
11
class GraphBuilder
12
{
13
    /** @var Graph */
14
    private $graph;
15
16
    /**
17
     * @param $models
18
     * @return Graph
19
     */
20
    public function buildGraph(Collection $models) : Graph
21
    {
22
        $this->graph = new Graph();
23
24
        foreach (config('erd-generator.graph') as $key => $value) {
25
            $this->graph->{"set{$key}"}($value);
26
        }
27
28
        $this->addModelsToGraph($models);
29
30
        return $this->graph;
31
    }
32
33
    protected function getTableColumnsFromModel(EloquentModel $model)
34
    {
35
        try {
36
37
            $table = $model->getConnection()->getTablePrefix() . $model->getTable();
38
            $schema = $model->getConnection()->getDoctrineSchemaManager($table);
39
            $databasePlatform = $schema->getDatabasePlatform();
40
            $databasePlatform->registerDoctrineTypeMapping('enum', 'string');
41
42
            $database = null;
43
44
            if (strpos($table, '.')) {
45
                list($database, $table) = explode('.', $table);
46
            }
47
48
            return $schema->listTableColumns($table, $database);
49
        } catch (\Throwable $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
50
        }
51
52
        return [];
53
    }
54
55
    protected function getModelLabel(EloquentModel $model, string $label)
56
    {
57
58
        $table = '<<table width="100%" height="100%" border="0" margin="0" cellborder="1" cellspacing="0" cellpadding="10">' . PHP_EOL;
59
        $table .= '<tr width="100%"><td width="100%" bgcolor="'.config('erd-generator.table.header_background_color').'"><font color="'.config('erd-generator.table.header_font_color').'">' . $label . '</font></td></tr>' . PHP_EOL;
60
61
        if (config('erd-generator.use_db_schema')) {
62
            $columns = $this->getTableColumnsFromModel($model);
63
            foreach ($columns as $column) {
64
                $label = $column->getName();
65
                if (config('erd-generator.use_column_types')) {
66
                    $label .= ' ('.$column->getType()->getName().')';
67
                }
68
                $table .= '<tr width="100%"><td port="' . $column->getName() . '" align="left" width="100%"  bgcolor="'.config('erd-generator.table.row_background_color').'"><font color="'.config('erd-generator.table.row_font_color').'" >' . $label . '</font></td></tr>' . PHP_EOL;
69
            }
70
        }
71
72
        $table .= '</table>>';
73
74
        return $table;
75
    }
76
77
    protected function addModelsToGraph(Collection $models)
78
    {
79
        // Add models to graph
80
        $models->map(function (Model $model) {
81
            $eloquentModel = app($model->getModel());
82
            $this->addNodeToGraph($eloquentModel, $model->getNodeName(), $model->getLabel());
83
        });
84
85
        // Create relations
86
        $models->map(function ($model) {
87
            $this->addRelationToGraph($model);
88
        });
89
    }
90
91
    protected function addNodeToGraph(EloquentModel $eloquentModel, string $nodeName, string $label)
92
    {
93
        $node = Node::create($nodeName);
94
        $node->setLabel($this->getModelLabel($eloquentModel, $label));
95
96
        foreach (config('erd-generator.node') as $key => $value) {
97
            $node->{"set{$key}"}($value);
98
        }
99
100
        $this->graph->setNode($node);
101
    }
102
103
    protected function addRelationToGraph(Model $model)
104
    {
105
106
        $modelNode = $this->graph->findNode($model->getNodeName());
107
108
        /** @var ModelRelation $relation */
109
        foreach ($model->getRelations() as $relation) {
110
            $relatedModelNode = $this->graph->findNode($relation->getModelNodeName());
111
112
            if ($relatedModelNode !== null) {
113
                $this->connectByRelation($model, $relation, $modelNode, $relatedModelNode);
114
            }
115
        }
116
    }
117
118
    /**
119
     * @param Node $modelNode
120
     * @param Node $relatedModelNode
121
     * @param ModelRelation $relation
122
     */
123
    protected function connectNodes(Node $modelNode, Node $relatedModelNode, ModelRelation $relation): void
124
    {
125
        $edge = Edge::create($modelNode, $relatedModelNode);
126
        $edge->setFromPort($relation->getLocalKey());
0 ignored issues
show
Are you sure the usage of $relation->getLocalKey() targeting BeyondCode\ErdGenerator\...Relation::getLocalKey() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
127
        $edge->setToPort($relation->getForeignKey());
128
        $edge->setLabel(' ');
129
        $edge->setXLabel($relation->getType() . PHP_EOL . $relation->getName());
130
131
        foreach (config('erd-generator.edge') as $key => $value) {
132
            $edge->{"set{$key}"}($value);
133
        }
134
135
        foreach (config('erd-generator.relations.' . $relation->getType(), []) as $key => $value) {
136
            $edge->{"set{$key}"}($value);
137
        }
138
139
        $this->graph->link($edge);
140
    }
141
142
    /**
143
     * @param Model $model
144
     * @param ModelRelation $relation
145
     * @param Node $modelNode
146
     * @param Node $relatedModelNode
147
     * @return void
148
     */
149
    protected function connectBelongsToMany(
150
        Model $model,
151
        ModelRelation $relation,
152
        Node $modelNode,
153
        Node $relatedModelNode
154
    ): void {
155
        $relationName = $relation->getName();
156
        $eloquentModel = app($model->getModel());
157
158
        /** @var BelongsToMany $eloquentRelation */
159
        $eloquentRelation = $eloquentModel->$relationName();
160
161
        if (!$eloquentRelation instanceof BelongsToMany) {
0 ignored issues
show
$eloquentRelation is always a sub-type of Illuminate\Database\Eloq...Relations\BelongsToMany.
Loading history...
162
            return;
163
        }
164
165
        $pivotClass = $eloquentRelation->getPivotClass();
166
167
        try {
168
            /** @var EloquentModel $relationModel */
169
            $pivotModel = app($pivotClass);
170
            $pivotModel->setTable($eloquentRelation->getTable());
171
            $label = (new \ReflectionClass($pivotClass))->getShortName();
172
            $pivotTable = $eloquentRelation->getTable();
173
            $this->addNodeToGraph($pivotModel, $pivotTable, $label);
174
175
            $pivotModelNode = $this->graph->findNode($pivotTable);
176
177
            $relation = new ModelRelation(
178
                $relationName,
179
                'BelongsToMany',
180
                $model->getModel(),
181
                $eloquentRelation->getParent()->getKeyName(),
182
                $eloquentRelation->getForeignPivotKeyName()
183
            );
184
185
            $this->connectNodes($modelNode, $pivotModelNode, $relation);
186
187
            $relation = new ModelRelation(
188
                $relationName,
189
                'BelongsToMany',
190
                $model->getModel(),
191
                $eloquentRelation->getRelatedPivotKeyName(),
192
                $eloquentRelation->getRelated()->getKeyName()
193
            );
194
195
            $this->connectNodes($pivotModelNode, $relatedModelNode, $relation);
196
        } catch (\ReflectionException $e){}
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
197
    }
198
199
    /**
200
     * @param Model $model
201
     * @param ModelRelation $relation
202
     * @param Node $modelNode
203
     * @param Node $relatedModelNode
204
     */
205
    protected function connectByRelation(
206
        Model $model,
207
        ModelRelation $relation,
208
        Node $modelNode,
209
        Node $relatedModelNode
210
    ): void {
211
212
        if ($relation->getType() === 'BelongsToMany') {
213
            $this->connectBelongsToMany($model, $relation, $modelNode, $relatedModelNode);
214
            return;
215
        }
216
217
        $this->connectNodes($modelNode, $relatedModelNode, $relation);
218
    }
219
}
220