DFSSorter   A
last analyzed

Complexity

Total Complexity 6

Size/Duplication

Total Lines 84
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
dl 0
loc 84
ccs 20
cts 20
cp 1
rs 10
c 0
b 0
f 0
wmc 6
lcom 1
cbo 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A addItem() 0 8 1
A sort() 0 11 2
A dfs() 0 16 3
1
<?php
2
/**
3
 * Spiral Framework.
4
 *
5
 * @license   MIT
6
 * @author    Lev Seleznev
7
 */
8
9
namespace Spiral\Support;
10
11
/**
12
 * Topological Sorting vs Depth First Traversal (DFS)
13
 * https://en.wikipedia.org/wiki/Topological_sorting.
14
 */
15
class DFSSorter
16
{
17
    const STATE_NEW    = 1;
18
    const STATE_PASSED = 2;
19
20
    /**
21
     * @var array string[]
22
     */
23
    private $keys = [];
24
25
    /**
26
     * @var array
27
     */
28
    private $states = [];
29
30
    /**
31
     * @var array mixed[]
32
     */
33
    private $stack = [];
34
35
    /**
36
     * @var array mixed[]
37
     */
38
    private $objects = [];
39
40
    /**
41
     * @var array mixed[]
42
     */
43
    private $dependencies = [];
44
45
    /**
46
     * @param string $key          Item key, has to be used as reference in dependencies.
47
     * @param mixed  $item
48
     * @param array  $dependencies Must include keys object depends on.
49
     *
50
     * @return self
51
     */
52 3
    public function addItem(string $key, $item, array $dependencies): DFSSorter
53
    {
54 3
        $this->keys[] = $key;
55 3
        $this->objects[$key] = $item;
56 3
        $this->dependencies[$key] = $dependencies;
57
58 3
        return $this;
59
    }
60
61
    /**
62
     * Return sorted stack.
63
     *
64
     * @return array
65
     */
66 3
    public function sort(): array
67
    {
68 3
        $items = array_values($this->keys);
69
70 3
        $this->states = $this->stack = [];
71 3
        foreach ($items as $item) {
72 3
            $this->dfs($item, $this->dependencies[$item]);
73
        }
74
75 3
        return $this->stack;
76
    }
77
78
    /**
79
     * @param string $key
80
     * @param array  $dependencies
81
     */
82 3
    private function dfs(string $key, array $dependencies)
83
    {
84 3
        if (isset($this->states[$key])) {
85 3
            return;
86
        }
87
88 3
        $this->states[$key] = self::STATE_NEW;
89 3
        foreach ($dependencies as $dependency) {
90 3
            $this->dfs($dependency, $this->dependencies[$dependency]);
91
        }
92
93 3
        $this->stack[] = $this->objects[$key];
94 3
        $this->states[$key] = self::STATE_PASSED;
95
96 3
        return;
97
    }
98
}
99