Completed
Branch dev (35fed3)
by Dennis
02:04
created

WzItem   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 194
Duplicated Lines 0 %

Coupling/Cohesion

Components 3
Dependencies 2

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 25
lcom 3
cbo 2
dl 0
loc 194
ccs 68
cts 68
cp 1
rs 10
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 11 2
A getId() 0 4 1
A getLabel() 0 13 2
A getLabels() 0 4 1
A getLevel() 0 4 1
A getParent() 0 4 1
A getParentByLevel() 0 18 4
A addChild() 0 13 3
A getChildren() 0 4 1
B getChildrenByLevel() 0 31 6
A buildLevelOutOfBounds() 0 4 1
A isInLevelBounds() 0 4 2
1
<?php
2
3
/**
4
 * (c) Dennis Meckel
5
 *
6
 * For the full copyright and license information,
7
 * please view the LICENSE file that was distributed with this source code.
8
 */
9
10
namespace Rayne\wz2008\Graph;
11
12
use InvalidArgumentException;
13
use OutOfBoundsException;
14
use Rayne\wz2008\Graph\Exception\InvalidParentException;
15
use SplQueue;
16
17
class WzItem implements WzItemInterface
18
{
19
    /**
20
     * @var WzItemInterface[]
21
     */
22
    private $children = [];
23
24
    /**
25
     * @var string
26
     */
27
    private $id;
28
29
    /**
30
     * @var string[]
31
     */
32
    private $labels;
33
34
    /**
35
     * @var int
36
     */
37
    private $level;
38
39
    /**
40
     * @var WzItemInterface|null
41
     */
42
    private $parent;
43
44
    /**
45
     * @param string $id
46
     * @param string[] $labels `Language Code => Translated Label` map.
47
     * @param int $level
48
     * @param WzItemInterface|null $parent
49
     */
50 36
    public function __construct($id, array $labels, $level, WzItemInterface $parent = null)
51
    {
52 36
        $this->id = $id;
53 36
        $this->labels = $labels;
54 36
        $this->level = (int) $level;
55 36
        $this->parent = $parent;
56
57 36
        if ($parent) {
58 18
            $parent->addChild($this);
59 6
        }
60 36
    }
61
62
    /**
63
     * @inheritdoc
64
     */
65 27
    public function getId()
66
    {
67 27
        return $this->id;
68
    }
69
70
    /**
71
     * @inheritdoc
72
     */
73 12
    public function getLabel($langCode)
74
    {
75 12
        $code = strtolower($langCode);
76
77 12
        if (isset($this->labels[$code])) {
78 12
            return $this->labels[$code];
79
        }
80
81 3
        throw new InvalidArgumentException(sprintf(
82 3
            'Unsupported language code `%s`. Supported codes: `%s`.',
83 1
            $langCode,
84 3
            implode(',', array_keys($this->labels))));
85
    }
86
87
    /**
88
     * @inheritdoc
89
     */
90 3
    public function getLabels()
91
    {
92 3
        return $this->labels;
93
    }
94
95
    /**
96
     * @inheritdoc
97
     */
98 18
    public function getLevel()
99
    {
100 18
        return $this->level;
101
    }
102
103
    /**
104
     * @inheritdoc
105
     */
106 21
    public function getParent()
107
    {
108 21
        return $this->parent;
109
    }
110
111
    /**
112
     * @inheritdoc
113
     */
114 9
    public function getParentByLevel($level)
115
    {
116 9
        if (!$this->isInLevelBounds($level)) {
117 3
            throw $this->buildLevelOutOfBounds($level);
118
        }
119
120 6
        if ($level >= $this->getLevel()) {
121 6
            return null;
122
        }
123
124 6
        $parent = $this;
125
126 6
        for ($i = $this->getLevel(); $i > $level; $i--) {
127 6
            $parent = $parent->getParent();
128 2
        }
129
130 6
        return $parent;
131
    }
132
133
    /**
134
     * @inheritdoc
135
     */
136 18
    public function addChild(WzItemInterface $child)
137
    {
138 18
        if ($child->getParent() !== $this) {
139 3
            throw new InvalidParentException(sprintf(
140 3
                "The parent of `%s` is invalid. Expected `%s` but got `%s`.",
141 3
                $child->getId(),
142 3
                $this->getId(),
143 3
                $child->getParent() ? $child->getParent()->getId() : ''));
144
        }
145
146 18
        $this->children[] = $child;
147 18
        return $this;
148
    }
149
150
    /**
151
     * @inheritdoc
152
     */
153 12
    public function getChildren()
154
    {
155 12
        return $this->children;
156
    }
157
158
    /**
159
     * @inheritdoc
160
     */
161 12
    public function getChildrenByLevel($level)
162
    {
163 12
        if (!$this->isInLevelBounds($level)) {
164 3
            throw $this->buildLevelOutOfBounds($level);
165
        }
166
167 9
        if ($this->getLevel() >= $level) {
168 9
            return [];
169
        }
170
171 6
        $result = [];
172
173 6
        $queue = new SplQueue();
174 6
        $queue->enqueue($this);
175
176 6
        while (!$queue->isEmpty()) {
177
            /* @var WzItemInterface $item */
178 6
            $item = $queue->dequeue();
179
180 6
            if ($item->getLevel() == $level) {
181 6
                $result[] = $item;
182 6
                continue;
183
            }
184
185 6
            foreach ($item->getChildren() as $child) {
186 6
                $queue->enqueue($child);
187 2
            }
188 2
        }
189
190 6
        return $result;
191
    }
192
193
    /**
194
     * @param int $level
195
     * @return OutOfBoundsException
196
     */
197 6
    private function buildLevelOutOfBounds($level)
198
    {
199 6
        return new OutOfBoundsException(sprintf('Unknown level `%s`.', $level));
200
    }
201
202
    /**
203
     * @param int $level
204
     * @return bool
205
     */
206 21
    private function isInLevelBounds($level)
207
    {
208 21
        return self::LEVEL_SECTION <= $level && $level <= self::LEVEL_SUBCLASS;
209
    }
210
}
211