Passed
Push — master ( 8506c6...ecf2bb )
by SignpostMarv
03:03
created

RecallDaftNestedObjectTreeWithObject()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 21
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 11
nc 4
nop 3
dl 0
loc 21
ccs 11
cts 11
cp 1
crap 3
rs 9.3142
c 0
b 0
f 0
1
<?php
2
/**
3
* Base daft objects.
4
*
5
* @author SignpostMarv
6
*/
7
declare(strict_types=1);
8
9
namespace SignpostMarv\DaftObject;
10
11
use RuntimeException;
12
13
abstract class DaftObjectMemoryTree extends DaftObjectMemoryRepository implements DaftNestedObjectTree
14
{
15 54
    public function RecallDaftNestedObjectFullTree(int $relativeDepthLimit = null) : array
16
    {
17
        /**
18
        * @var string[] $props
19
        */
20 54
        $props = $this->type::DaftObjectIdProperties();
21
22
        /**
23
        * @var DaftNestedObject[] $out
24
        */
25 54
        $out = array_map(
26
            function (array $id) : DaftNestedObject {
27 54
                $out = $this->RecallDaftObject($id);
28
29 54
                if ( ! ($out instanceof DaftNestedObject)) {
30 2
                    throw new RuntimeException('Could not retrieve leaf from tree!');
31
                }
32
33 52
                return $out;
34 54
            },
35 54
            array_map(
36
                /**
37
                * @param array<string, scalar|null> $row
38
                */
39
                function (array $row) use ($props) : array {
40
                    /**
41
                    * @var array<string, scalar|null> $out
42
                    */
43 54
                    $out = [];
44
45
                    /**
46
                    * @var string $prop
47
                    */
48 54
                    foreach ($props as $prop) {
49 54
                        $out[$prop] = $row[$prop] ?? null;
50
                    }
51
52 54
                    return $out;
53 54
                },
54 54
                (array) $this->data
55
            )
56
        );
57
58
        usort($out, function (DaftNestedObject $a, DaftNestedObject $b) : int {
59 52
            return $a->GetIntNestedLeft() <=> $b->GetIntNestedLeft();
60 52
        });
61
62 52
        if (is_int($relativeDepthLimit)) {
63 32
            $out = array_filter(
64 32
                $out,
65
                function (DaftNestedObject $e) use ($relativeDepthLimit) : bool {
66 32
                    return $e->GetIntNestedLevel() <= $relativeDepthLimit;
67 32
                }
68
            );
69
        }
70
71 52
        return $out;
72
    }
73
74 14
    public function CountDaftNestedObjectFullTree(int $relativeDepthLimit = null) : int
75
    {
76 14
        return count($this->RecallDaftNestedObjectFullTree($relativeDepthLimit));
77
    }
78
79
    /**
80
    * {@inheritdoc}
81
    */
82 32
    public function RecallDaftNestedObjectTreeWithObject(
83
        DaftNestedObject $root,
84
        bool $includeRoot,
85
        ? int $limit
86
    ) : array {
87 32
        $left = $root->GetIntNestedLeft();
88 32
        $right = $root->GetIntNestedRight();
89 32
        $limit = is_int($limit) ? ($root->GetIntNestedLevel() + $limit) : null;
90
91 32
        $leaves = $this->RecallDaftNestedObjectFullTree();
92
93 32
        if (is_int($limit)) {
94
            $leaves = array_filter($leaves, function (DaftNestedObject $e) use ($limit) : bool {
95 26
                return $e->GetIntNestedLevel() <= $limit;
96 26
            });
97
        }
98
99 32
        return array_values(array_filter(
100 32
            $leaves,
101
            function (DaftNestedObject $e) use ($includeRoot, $left, $right) : bool {
102 32
                return $this->FilterLeaf($includeRoot, $left, $right, $e);
103 32
            }
104
        ));
105
    }
106
107 20
    public function CountDaftNestedObjectTreeWithObject(
108
        DaftNestedObject $root,
109
        bool $includeRoot,
110
        ? int $relativeDepthLimit
111
    ) : int {
112 20
        return count(
113 20
            $this->RecallDaftNestedObjectTreeWithObject($root, $includeRoot, $relativeDepthLimit)
114
        );
115
    }
116
117 44
    public function RecallDaftNestedObjectTreeWithId(
118
        $id,
119
        bool $includeRoot,
120
        ? int $relativeDepthLimit
121
    ) : array {
122 44
        $object = $this->RecallDaftObject($id);
123
124
        return
125 44
            ($object instanceof DaftNestedObject)
126 16
                ? $this->RecallDaftNestedObjectTreeWithObject(
127 16
                    $object,
128 16
                    $includeRoot,
129 16
                    $relativeDepthLimit
130
                )
131
                : (
132 28
                    ((array) $id === (array) $this->GetNestedObjectTreeRootId())
133 28
                        ? $this->RecallDaftNestedObjectFullTree(0)
134 44
                        : []
135
                );
136
    }
137
138 4
    public function CountDaftNestedObjectTreeWithId(
139
        $id,
140
        bool $includeRoot,
141
        ? int $relativeDepthLimit
142
    ) : int {
143 4
        return count($this->RecallDaftNestedObjectTreeWithId(
144 4
            $id,
145 4
            $includeRoot,
146 4
            $relativeDepthLimit
147
        ));
148
    }
149
150 4
    public function RecallDaftNestedObjectPathToObject(
151
        DaftNestedObject $leaf,
152
        bool $includeLeaf
153
    ) : array {
154 4
        $left = $leaf->GetIntNestedLeft();
155 4
        $right = $leaf->GetIntNestedRight();
156
157 4
        if ( ! $includeLeaf) {
158 4
            --$left;
159 4
            ++$right;
160
        }
161
162 4
        return array_values(array_filter(
163 4
            $this->RecallDaftNestedObjectFullTree(),
164
            function (DaftNestedObject $e) use ($left, $right) : bool {
165 4
                return $e->GetIntNestedLeft() <= $left && $e->GetIntNestedRight() >= $right;
166 4
            }
167
        ));
168
    }
169
170 4
    public function CountDaftNestedObjectPathToObject(
171
        DaftNestedObject $leaf,
172
        bool $includeLeaf
173
    ) : int {
174 4
        return count($this->RecallDaftNestedObjectPathToObject($leaf, $includeLeaf));
175
    }
176
177 4
    public function RecallDaftNestedObjectPathToId($id, bool $includeLeaf) : array
178
    {
179 4
        $object = $this->RecallDaftObject($id);
180
181
        return
182 4
            ($object instanceof DaftNestedObject)
183 4
                ? $this->RecallDaftNestedObjectPathToObject($object, $includeLeaf)
184 4
                : [];
185
    }
186
187
    /*
188
    * @param mixed $id
189
    */
190 4
    public function CountDaftNestedObjectPathToId($id, bool $includeLeaf) : int
191
    {
192 4
        return count($this->RecallDaftNestedObjectPathToId($id, $includeLeaf));
193
    }
194
195 48
    public function CompareObjects(DaftNestedObject $a, DaftNestedObject $b) : int
196
    {
197 48
        return $a->GetIntNestedSortOrder() <=> $b->GetIntNestedSortOrder();
198
    }
199
200 32
    protected function FilterLeaf(
201
        bool $includeRoot,
202
        int $left,
203
        int $right,
204
        DaftNestedObject $e
205
    ) : bool {
206 32
        if ($includeRoot) {
207 4
            return $e->GetIntNestedLeft() >= $left && $e->GetIntNestedRight() <= $right;
208
        }
209
210 32
        return $e->GetIntNestedLeft() > $left && $e->GetIntNestedRight() < $right;
211
    }
212
213 96
    protected function RememberDaftObjectData(DefinesOwnIdPropertiesInterface $object) : void
214
    {
215 96
        static::ThrowIfNotType($object, DaftNestedObject::class, 1, __METHOD__);
216
217 96
        parent::RememberDaftObjectData($object);
218 96
    }
219
220
    /**
221
    * @param DaftObject|string $object
222
    */
223 146
    protected static function ThrowIfNotType(
224
        $object,
225
        string $type,
226
        int $argument,
227
        string $function
228
    ) : void {
229 146
        parent::ThrowIfNotType($object, $type, $argument, $function);
230
231 146
        if ( ! is_a($object, DaftNestedObject::class, is_string($object))) {
232 2
            throw new DaftObjectRepositoryTypeByClassMethodAndTypeException(
233 2
                $argument,
234 2
                static::class,
235 2
                $function,
236 2
                DaftNestedObject::class,
237 2
                is_string($object) ? $object : get_class($object)
238
            );
239
        }
240 144
    }
241
}
242