GraphItem   B
last analyzed

Complexity

Total Complexity 50

Size/Duplication

Total Lines 329
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
wmc 50
eloc 102
c 1
b 0
f 1
dl 0
loc 329
rs 8.4

16 Methods

Rating   Name   Duplication   Size   Complexity  
B getNextItemsMap() 0 19 7
A deleteNextItem() 0 19 5
A __construct() 0 4 1
A setData() 0 4 1
A addNextItem() 0 11 2
A toArray() 0 7 1
B getPrevItemsMap() 0 19 7
A setId() 0 4 1
A getData() 0 3 1
A getNextItems() 0 24 6
A deletePrevItem() 0 19 5
A getPrevItem() 0 10 2
A getNextItem() 0 10 2
A getPrevItems() 0 24 6
A addPrevItem() 0 11 2
A getId() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like GraphItem often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use GraphItem, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Smoren\Containers\Structs;
4
5
use Smoren\Containers\Exceptions\GraphException;
6
7
class GraphItem
8
{
9
    /**
10
     * @var string item ID
11
     */
12
    protected string $id;
13
    /**
14
     * @var mixed item data
15
     */
16
    protected $data;
17
    /**
18
     * @var GraphItem[][] next items mapped by item IDs and type
19
     */
20
    protected array $nextItemMap = [];
21
    /**
22
     * @var GraphItem[][] previous items mapped by item IDs and type
23
     */
24
    protected array $prevItemMap = [];
25
26
    /**
27
     * GraphItem constructor.
28
     * @param string $id item ID
29
     * @param mixed $data item data
30
     */
31
    public function __construct(string $id, $data)
32
    {
33
        $this->id = $id;
34
        $this->data = $data;
35
    }
36
37
    /**
38
     * Returns item ID
39
     * @return string
40
     */
41
    public function getId(): string
42
    {
43
        return $this->id;
44
    }
45
46
    /**
47
     * Sets item ID
48
     * @param string $id
49
     * @return self
50
     */
51
    public function setId(string $id): self
52
    {
53
        $this->id = $id;
54
        return $this;
55
    }
56
57
    /**
58
     * Returns item data
59
     * @return mixed
60
     */
61
    public function getData()
62
    {
63
        return $this->data;
64
    }
65
66
    /**
67
     * Sets item data
68
     * @param mixed $data
69
     * @return self
70
     */
71
    public function setData($data): self
72
    {
73
        $this->data = $data;
74
        return $this;
75
    }
76
77
    /**
78
     * Returns previous item by ID
79
     * @param string $id item ID
80
     * @param string $type link type
81
     * @return GraphItem
82
     * @throws GraphException
83
     */
84
    public function getPrevItem(string $id, string $type): GraphItem
85
    {
86
        if(!isset($this->prevItemMap[$type][$id])) {
87
            throw new GraphException(
88
                "ID '{$id}' not exists",
89
                GraphException::STATUS_ID_NOT_EXIST
90
            );
91
        }
92
93
        return $this->prevItemMap[$type][$id];
94
    }
95
96
    /**
97
     * Returns previous items list
98
     * @param string|null $type link type
99
     * @return GraphItem[]
100
     * @throws GraphException
101
     */
102
    public function getPrevItems(?string $type = null): array
103
    {
104
        $result = [];
105
106
        if($type === null) {
107
            foreach($this->prevItemMap as $itemMap) {
108
                foreach($itemMap as $itemId => $item) {
109
                    $result[$itemId] = $item;
110
                }
111
            }
112
        } else {
113
            if(!isset($this->prevItemMap[$type])) {
114
                throw new GraphException(
115
                    "type '{$type}' not exist",
116
                    GraphException::STATUS_TYPE_NOT_EXIST
117
                );
118
            }
119
120
            foreach($this->prevItemMap[$type] as $itemId => $item) {
121
                $result[$itemId] = $item;
122
            }
123
        }
124
125
        return array_values($result);
126
    }
127
128
    /**
129
     * Returns previous items map ([linkType => [itemId, ...], ...])
130
     * @param array|null $typesOnly
131
     * @param array|null $typesExclude
132
     * @return string[][]
133
     */
134
    public function getPrevItemsMap(?array $typesOnly = null, ?array $typesExclude = null): array
135
    {
136
        $result = [];
137
138
        foreach($this->prevItemMap as $type => $itemMap) {
139
            if(
140
                $typesOnly !== null && !in_array($type, $typesOnly) ||
0 ignored issues
show
introduced by
Consider adding parentheses for clarity. Current Interpretation: ($typesOnly !== null && ...y($type, $typesExclude), Probably Intended Meaning: $typesOnly !== null && (...($type, $typesExclude))
Loading history...
141
                $typesExclude !== null && in_array($type, $typesExclude)
142
            ) {
143
                continue;
144
            }
145
146
            $result[$type] = [];
147
            foreach($itemMap as $itemId => $item) {
148
                $result[$type][] = $itemId;
149
            }
150
        }
151
152
        return $result;
153
    }
154
155
    /**
156
     * Adds link to previous item
157
     * @param GraphItem $item item to link
158
     * @param string $type link type
159
     * @return $this
160
     */
161
    public function addPrevItem(GraphItem $item, string $type): self
162
    {
163
        $itemId = $item->getId();
164
165
        if(!isset($this->prevItemMap[$type])) {
166
            $this->prevItemMap[$type] = [];
167
        }
168
169
        $this->prevItemMap[$type][$itemId] = $item;
170
171
        return $this;
172
    }
173
174
    /**
175
     * Deletes link to previous item
176
     * @param string $itemId ID of item to delete
177
     * @param string|null $type link type
178
     * @return $this
179
     */
180
    public function deletePrevItem(string $itemId, ?string $type = null): self
181
    {
182
        if($type === null) {
183
            foreach($this->prevItemMap as $type => $itemMap) {
184
                $this->deletePrevItem($itemId, $type);
185
            }
186
187
            return $this;
188
        }
189
190
        if(isset($this->prevItemMap[$type][$itemId])) {
191
            unset($this->prevItemMap[$type][$itemId]);
192
193
            if(!count($this->prevItemMap[$type])) {
194
                unset($this->prevItemMap[$type]);
195
            }
196
        }
197
198
        return $this;
199
    }
200
201
    /**
202
     * Returns next item by ID
203
     * @param string $id next item ID
204
     * @param string $type link type
205
     * @return GraphItem
206
     * @throws GraphException
207
     */
208
    public function getNextItem(string $id, string $type): GraphItem
209
    {
210
        if(!isset($this->nextItemMap[$type][$id])) {
211
            throw new GraphException(
212
                "ID '{$id}' not exists",
213
                GraphException::STATUS_ID_NOT_EXIST
214
            );
215
        }
216
217
        return $this->nextItemMap[$type][$id];
218
    }
219
220
    /**
221
     * Returns previous items list
222
     * @param string|null $type
223
     * @return GraphItem[]
224
     * @throws GraphException
225
     */
226
    public function getNextItems(?string $type = null): array
227
    {
228
        $result = [];
229
230
        if($type === null) {
231
            foreach($this->nextItemMap as $itemMap) {
232
                foreach($itemMap as $itemId => $item) {
233
                    $result[$itemId] = $item;
234
                }
235
            }
236
        } else {
237
            if(!isset($this->nextItemMap[$type])) {
238
                throw new GraphException(
239
                    "type '{$type}' not exist",
240
                    GraphException::STATUS_TYPE_NOT_EXIST
241
                );
242
            }
243
244
            foreach($this->nextItemMap[$type] as $itemId => $item) {
245
                $result[$itemId] = $item;
246
            }
247
        }
248
249
        return array_values($result);
250
    }
251
252
    /**
253
     * Returns next items map ([linkType => [itemId, ...], ...])
254
     * @param array|null $typesOnly
255
     * @param array|null $typesExclude
256
     * @return string[][]
257
     */
258
    public function getNextItemsMap(?array $typesOnly = null, ?array $typesExclude = null): array
259
    {
260
        $result = [];
261
262
        foreach($this->nextItemMap as $type => $itemMap) {
263
            if(
264
                $typesOnly !== null && !in_array($type, $typesOnly) ||
0 ignored issues
show
introduced by
Consider adding parentheses for clarity. Current Interpretation: ($typesOnly !== null && ...y($type, $typesExclude), Probably Intended Meaning: $typesOnly !== null && (...($type, $typesExclude))
Loading history...
265
                $typesExclude !== null && in_array($type, $typesExclude)
266
            ) {
267
                continue;
268
            }
269
270
            $result[$type] = [];
271
            foreach($itemMap as $itemId => $item) {
272
                $result[$type][] = $itemId;
273
            }
274
        }
275
276
        return $result;
277
    }
278
279
    /**
280
     * Adds link to next item
281
     * @param GraphItem $item item to link
282
     * @param string $type link type
283
     * @return $this
284
     */
285
    public function addNextItem(GraphItem $item, string $type): self
286
    {
287
        $itemId = $item->getId();
288
289
        if(!isset($this->nextItemMap[$type])) {
290
            $this->nextItemMap[$type] = [];
291
        }
292
293
        $this->nextItemMap[$type][$itemId] = $item;
294
295
        return $this;
296
    }
297
298
    /**
299
     * Deletes link to next item
300
     * @param string $itemId ID of item to delete
301
     * @param string|null $type link type
302
     * @return $this
303
     */
304
    public function deleteNextItem(string $itemId, ?string $type = null): self
305
    {
306
        if($type === null) {
307
            foreach($this->nextItemMap as $type => $itemMap) {
308
                $this->deleteNextItem($itemId, $type);
309
            }
310
311
            return $this;
312
        }
313
314
        if(isset($this->nextItemMap[$type][$itemId])) {
315
            unset($this->nextItemMap[$type][$itemId]);
316
317
            if(!count($this->nextItemMap[$type])) {
318
                unset($this->nextItemMap[$type]);
319
            }
320
        }
321
322
        return $this;
323
    }
324
325
    /**
326
     * Representates as array
327
     * @return array
328
     */
329
    public function toArray(): array
330
    {
331
        return [
332
            'id' => $this->id,
333
            'data' => $this->data,
334
            'previous' => $this->getPrevItemsMap(),
335
            'next' => $this->getNextItemsMap(),
336
        ];
337
    }
338
}
339