Passed
Push — master ( 029172...056350 )
by Satoshi
02:16
created

UmlFormatter::getComponentByName()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 4
nc 3
nop 1
dl 0
loc 9
rs 10
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
namespace DependencyAnalyzer\Inspector\GraphFormatter;
5
6
use DependencyAnalyzer\DependencyGraph;
7
use DependencyAnalyzer\Inspector\RuleViolationDetector\Component;
8
use DependencyAnalyzer\Matcher\ClassNameMatcher;
9
10
class UmlFormatter
11
{
12
    /**
13
     * @var DependencyGraph
14
     */
15
    protected $graph;
16
17
    /**
18
     * @var array
19
     */
20
    protected $ruleDefinition;
21
22
    /**
23
     * @var Component[]
24
     */
25
    protected $components = [];
26
27
    protected $groupedClasses = [];
28
29
    /**
30
     * @var ClassNameMatcher
31
     */
32
    protected $excludeDefinition;
33
34
    /**
35
     * @param DependencyGraph $graph
36
     * @param Component[] $components
37
     */
38
    public function __construct(DependencyGraph $graph, array $components = [])
39
    {
40
        $this->graph = $this->createFoldedGraph($graph, $components);
41
        $this->components = $components;
42
//        $this->ruleDefinition = $ruleDefinition;
43
44
//        if (isset($ruleDefinition['namespace'])) {
45
//            foreach ($ruleDefinition['namespace'] as $componentName => $componentDefinition) {
46
//                $this->components[] = new Component($componentName, new ClassNameMatcher($componentDefinition));
47
//            }
48
//        }
49
//        if (isset($ruleDefinition['exclude'])) {
50
//            $this->excludeDefinition = new ClassNameMatcher($ruleDefinition['exclude']);
51
//        }
52
//        if (isset($ruleDefinition['group'])) {
53
//            foreach ($ruleDefinition['group'] as $groupName => $groupDefinition) {
54
//                $this->graph = $this->graph->groupByPattern($groupName, new ClassNameMatcher($groupDefinition));
55
//            }
56
//        }
57
58
        $this->groupedClasses = $this->getGroupedClasses($this->graph, $this->components);
59
    }
60
61
    public function format()
62
    {
63
        $output = '@startuml' . PHP_EOL;
64
65
        foreach ($this->groupedClasses as $componentName => $classNames) {
66
            $component = $this->getComponentByName($componentName);
67
68
            if (!is_null($component) && $component->getAttribute('namespace')) {
69
                $output .= "namespace {$component->getName()} {" . PHP_EOL;
70
            }
71
72
            foreach ($classNames as $className) {
73
                $output .= "class {$className} {" . PHP_EOL;
74
                $output .= '}' . PHP_EOL;
75
            }
76
77
            if (!is_null($component) && $component->getAttribute('namespace')) {
78
                $output .= '}' . PHP_EOL;
79
            }
80
        }
81
82
//        foreach ($this->components as $component) {
83
//            if ($component->getAttribute('namespace')) {
84
//                $output .= "namespace {$component->getName()} {" . PHP_EOL;
85
//            }
86
//
87
//            foreach ($this->graph->getClasses() as $class) {
88
//                if ($component->isBelongedTo($class->getId())) {
89
//                    if (!$this->isExcludeClass($class->getId())) {
90
//                        $output .= "class {$class->getId()} {" . PHP_EOL;
91
//                        $output .= '}' . PHP_EOL;
92
//                    }
93
//                }
94
//            }
95
//
96
//            if ($component->getAttribute('namespace')) {
97
//                $output .= '}' . PHP_EOL;
98
//            }
99
//        }
100
//
101
//        foreach ($this->graph->getClasses() as $class) {
102
//            if ($this->isExcludeClass($class->getId())) {
103
//                continue;
104
//            }
105
//
106
//            foreach ($this->components as $component) {
107
//                if ($component->getAttribute('namespace') && $component->isBelongedTo($class->getId())) {
108
//                    continue 2;
109
//                }
110
//            }
111
//
112
//            $output .= "class {$class->getId()} {" . PHP_EOL;
113
//            $output .= '}' . PHP_EOL;
114
//        }
115
116
117
118
119
//        foreach ($this->groupedClasses as $componentName => $classes) {
120
//            if ($componentName !== '') {
121
//                $output .= "namespace {$componentName} {" . PHP_EOL;
122
//            }
123
//
124
//            foreach ($classes as $class) {
125
//                if (!$this->isExcludeClass($class)) {
126
//                    $output .= "class {$class} {" . PHP_EOL;
127
//                    $output .= '}' . PHP_EOL;
128
//                }
129
//            }
130
//
131
//            if ($componentName !== '') {
132
//                $output .= '}' . PHP_EOL;
133
//            }
134
//        }
135
136
        foreach ($this->graph->getDependencyArrows() as $edge) {
137
            $depender = $edge->getVertexStart();
138
            $dependee = $edge->getVertexEnd();
139
140
            if ($this->isExcludeClass($depender->getId()) || $this->isExcludeClass($dependee->getId())) {
141
                continue;
142
            }
143
            $output .= "{$this->searchGroupedClasses($depender->getId())} --> {$this->searchGroupedClasses($dependee->getId())}" . PHP_EOL;
144
        }
145
146
        $output .= '@enduml';
147
148
        return $output;
149
    }
150
151
    protected function isExcludeClass(string $className)
152
    {
153
        if ($this->excludeDefinition) {
154
            return $this->excludeDefinition->isMatch($className);
155
        }
156
157
        return false;
158
    }
159
160
    /**
161
     * @param DependencyGraph $graph
162
     * @param Component[] $components
163
     * @return DependencyGraph
164
     */
165
    protected function createFoldedGraph(DependencyGraph $graph, array $components): DependencyGraph
166
    {
167
        foreach ($components as $component) {
168
            if ($component->getAttribute('folding')) {
169
                $graph = $graph->groupByPattern($component->getName(), $component->getDefineMatcher());
170
            }
171
        }
172
173
        return $graph;
174
    }
175
176
    /**
177
     * @param DependencyGraph $graph
178
     * @param Component[] $components
179
     * @return array
180
     */
181
    protected function getGroupedClasses(DependencyGraph $graph, array $components): array
182
    {
183
        $classNames = [];
184
185
        foreach ($graph->getClasses() as $class) {
186
            $key = $this->getBelongToComponent($class->getId(), $components);
187
            $classNames[$key][] = $class->getId();
188
//            $classNames[] = $class->getId();
189
        }
190
//        sort($classNames);
191
192
        return $classNames;
193
    }
194
195
    protected function getBelongToComponent(string $className, array $components): string
196
    {
197
        foreach ($components as $component) {
198
            if ($component->isBelongedTo($className)) {
199
                return $component->getName();
200
            }
201
        }
202
203
        return '';
204
    }
205
206
    protected function searchGroupedClasses(string $needle)
207
    {
208
        foreach ($this->groupedClasses as $componentName => $classes) {
209
            if ($componentName === '' || !$this->getComponentByName($componentName)->getAttribute('namespace')) {
210
                continue;
211
            }
212
213
            foreach ($classes as $class) {
214
                if ($class === $needle) {
215
                    if ($this->getComponentByName($componentName)->getAttribute('folding')) {
216
                        return $this->getComponentByName($componentName)->getName();
217
                    } else {
218
                        return "{$componentName}.$needle";
219
                    }
220
                }
221
            }
222
        }
223
224
        return $needle;
225
    }
226
227
    protected function getComponentByName(string $componentName): ?Component
228
    {
229
        foreach ($this->components as $component) {
230
            if ($component->getName() === $componentName) {
231
                return $component;
232
            }
233
        }
234
235
        return null;
236
    }
237
}
238