Passed
Push — master ( 7f6baf...50f068 )
by Satoshi
02:16
created

CycleDetector   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 64
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 25
dl 0
loc 64
rs 10
c 0
b 0
f 0
wmc 13

4 Methods

Rating   Name   Duplication   Size   Complexity  
A checkCycle() 0 4 2
A collectConnectedSubGraphs() 0 19 5
A inspect() 0 14 3
A addCycle() 0 9 3
1
<?php
2
declare(strict_types=1);
3
4
namespace DependencyAnalyzer\Inspector;
5
6
use DependencyAnalyzer\DependencyGraph;
7
use DependencyAnalyzer\DependencyGraph\Path;
8
use DependencyAnalyzer\Exceptions\LogicException;
9
use DependencyAnalyzer\Inspector\Responses\CycleDetectorResponse;
10
11
class CycleDetector
12
{
13
    /**
14
     * @var Path[]
15
     */
16
    protected $cycles = [];
17
18
    public function inspect(DependencyGraph $graph): CycleDetectorResponse
19
    {
20
        $subGraphs = $this->collectConnectedSubGraphs($graph);
21
22
        foreach ($subGraphs as $subGraph) {
23
            $subGraph->walkOnPath([$this, 'checkCycle']);
24
        }
25
26
        $response = new CycleDetectorResponse();
27
        foreach ($this->cycles as $cycle) {
28
            $response->addCycle($cycle->toArray());
29
        }
30
31
        return $response;
32
    }
33
34
    public function checkCycle(Path $path): void
35
    {
36
        if ($path->isSimpleCycle()) {
37
            $this->addCycle($path);
38
        }
39
    }
40
41
    protected function addCycle(Path $path): void
42
    {
43
        foreach ($this->cycles as $cycle) {
44
            if ($cycle->isEqual($path)) {
45
                return;
46
            }
47
        }
48
49
        $this->cycles[] = $path;
50
    }
51
52
    /**
53
     * @param DependencyGraph $graph
54
     * @return DependencyGraph[]
55
     */
56
    protected function collectConnectedSubGraphs(DependencyGraph $graph): array
57
    {
58
        $subGraphs = [];
59
60
        $visited = [];
61
        foreach ($graph->getClasses()->getMap() as $id => $vertex) {
62
            if (!isset($visited[$id])) {
63
                $subGraphs[] = $subGraph = $graph->getConnectedSubGraphsStartFrom($vertex);
64
65
                foreach ($subGraph->getClasses() as $subGraphVertex) {
66
                    $visited[$subGraphVertex->getId()] = true;
67
                }
68
            }
69
        }
70
71
        if ($graph->count() !== count($visited)) {
72
            throw new LogicException();
73
        }
74
        return $subGraphs;
75
    }
76
}
77