Passed
Push — master ( e0cef8...6995f6 )
by Smoren
02:40
created

TreeMaker::wrapItem()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 0
Metric Value
eloc 7
c 0
b 0
f 0
dl 0
loc 13
ccs 8
cts 8
cp 1
rs 10
cc 3
nc 3
nop 3
crap 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Smoren\TreeTools;
6
7
use Smoren\TypeTools\MapAccess;
8
use ArrayAccess;
9
use stdClass;
10
11
class TreeMaker
12
{
13
    /**
14
     * @param iterable<mixed> $list
15
     * @param string $idField
16
     * @param string $parentIdField
17
     * @param string $childrenContainerField
18
     * @param string $itemContainerField
19
     *
20
     * @return array<mixed>
21
     */
22 10
    public static function fromList(
23
        iterable $list,
24
        string $idField = 'id',
25
        string $parentIdField = 'parent_id',
26
        string $childrenContainerField = 'children',
27
        string $itemContainerField = 'item'
28
    ): array {
29 10
        $result = [];
30 10
        $map = [];
31
32 10
        foreach($list as $item) {
33 5
            $map[MapAccess::get($item, $idField)] = static::wrapItem(
34 5
                $item,
35 5
                $childrenContainerField,
36 5
                $itemContainerField
37 5
            );
38
        }
39
40 10
        foreach($map as &$item) {
41 5
            if(($parentId = static::getParentId($item, $parentIdField, $itemContainerField)) !== null) {
42 5
                $childrenContainer = &static::getChildrenContainer($map[$parentId], $childrenContainerField);
43 5
                $childrenContainer[] = &$item;
44
            } else {
45 5
                $result[] = &$item;
46
            }
47
        }
48
49 10
        return $result;
50
    }
51
52
    /**
53
     * @param mixed $item
54
     * @param string $parentIdField
55
     * @param string $itemContainerField
56
     *
57
     * @return scalar|null
58
     */
59 5
    protected static function getParentId($item, string $parentIdField, string $itemContainerField)
60
    {
61
        /** @var scalar|null $parentId */
62 5
        $parentId = MapAccess::get($item, $parentIdField);
63
64 5
        if($parentId !== null) {
65 4
            return $parentId;
66
        }
67
68 5
        return MapAccess::get(MapAccess::get($item, $itemContainerField), $parentIdField);
69
    }
70
71
    /**
72
     * @param mixed $item
73
     * @param string $childrenContainerField
74
     *
75
     * @return array<mixed>
76
     */
77 5
    protected static function &getChildrenContainer(&$item, string $childrenContainerField): array
78
    {
79 5
        if(is_array($item)) {
80 3
            return $item[$childrenContainerField];
81
        }
82
83 2
        return $item->{$childrenContainerField};
84
    }
85
86
    /**
87
     * @param mixed $item
88
     * @param string $childrenContainerField
89
     * @param string $itemContainerField
90
     *
91
     * @return array<mixed>|stdClass
92
     */
93 5
    protected static function wrapItem($item, string $childrenContainerField, string $itemContainerField)
94
    {
95 5
        if(is_array($item)) {
96 2
            $item[$childrenContainerField] = [];
97 2
            return $item;
98
        }
99
100 3
        if($item instanceof stdClass) {
101 2
            $item->{$childrenContainerField} = [];
102 2
            return $item;
103
        }
104
105 1
        return [$itemContainerField => &$item, $childrenContainerField => []];
106
    }
107
}
108