DaftObjectMemoryTree   A
last analyzed

Complexity

Total Complexity 27

Size/Duplication

Total Lines 303
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
eloc 78
dl 0
loc 303
ccs 88
cts 88
cp 1
rs 10
c 0
b 0
f 0
wmc 27

14 Methods

Rating   Name   Duplication   Size   Complexity  
A CountDaftNestedObjectPathToId() 0 3 1
A RecallDaftNestedObjectPathToId() 0 20 2
A RecallDaftNestedObjectPathToObject() 0 24 4
A CountDaftNestedObjectTreeWithId() 0 9 1
A CountDaftNestedObjectPathToObject() 0 5 1
A RememberDaftObject() 0 3 1
A CountDaftNestedObjectTreeWithObject() 0 7 1
A RecallDaftNestedObjectFullTree() 0 58 3
A RecallDaftNestedObjectTreeWithId() 0 26 3
A RecallDaftNestedObjectTreeWithObject() 0 24 3
A CountDaftNestedObjectFullTree() 0 3 1
A FilterLeaf() 0 11 4
A MapDataToObject() 0 12 1
A RecallDaftObject() 0 8 1
1
<?php
2
/**
3
* Base daft objects.
4
*
5
* @author SignpostMarv
6
*/
7
declare(strict_types=1);
8
9
namespace SignpostMarv\DaftObject;
10
11
/**
12
* @template T as DaftNestedObject
13
*
14
* @template-extends DaftObjectMemoryRepository<T>
15
*
16
* @template-implements DaftNestedObjectTree<T>
17
*/
18
abstract class DaftObjectMemoryTree extends DaftObjectMemoryRepository implements DaftNestedObjectTree
19
{
20
    const BOOL_DEFAULT_ASSUME_DOES_NOT_EXIST = false;
21
22
    const BOOL_DEFAULT_NO_MODIFY = 0;
23
24 90
    public function RecallDaftNestedObjectFullTree(int $relativeDepthLimit = null) : array
25
    {
26
        /**
27
        * @var array<int, DaftNestedObject>
28
        *
29
        * @psalm-var array<int, T>
30
        */
31 90
        $out = $this->memory;
32
33 90
        $outIds = [];
34
35 90
        foreach ($out as $obj) {
36
            /**
37
            * @var array<int, scalar|(scalar|array|object|null)[]>
38
            */
39 44
            $id = $obj->GetId();
40
41 44
            $outIds[] = $id;
42
        }
43
44
        /**
45
        * @var array<int, DaftNestedObject>
46
        *
47
        * @psalm-var array<int, T>
48
        */
49 90
        $fromMemory = array_filter(
50 90
            array_map([$this, 'MapDataToObject'], $this->data),
51
            function (DaftNestedObject $leaf) use ($outIds) : bool {
52 64
                return ! in_array($leaf->GetId(), $outIds, true);
53 90
            }
54
        );
55
56 90
        $out = array_merge($out, $fromMemory);
57
58 90
        usort(
59 90
            $out,
60
            /**
61
            * @psalm-param T $a
62
            * @psalm-param T $b
63
            */
64
            function (DaftNestedObject $a, DaftNestedObject $b) : int {
65 64
                return $a->GetIntNestedLeft() <=> $b->GetIntNestedLeft();
66 90
            }
67
        );
68
69 90
        if (is_int($relativeDepthLimit)) {
70 32
            $out = array_filter(
71 32
                $out,
72
                /**
73
                * @psalm-param T $e
74
                */
75
                function (DaftNestedObject $e) use ($relativeDepthLimit) : bool {
76 32
                    return $e->GetIntNestedLevel() <= $relativeDepthLimit;
77 32
                }
78
            );
79
        }
80
81 90
        return $out;
82
    }
83
84 90
    public function CountDaftNestedObjectFullTree(int $relativeDepthLimit = null) : int
85
    {
86 90
        return count($this->RecallDaftNestedObjectFullTree($relativeDepthLimit));
87
    }
88
89
    /**
90
    * {@inheritdoc}
91
    *
92
    * @psalm-param T $root
93
    *
94
    * @psalm-return array<int, T>
95
    */
96 40
    public function RecallDaftNestedObjectTreeWithObject(
97
        DaftNestedObject $root,
98
        bool $includeRoot,
99
        ? int $limit
100
    ) : array {
101 40
        $left = $root->GetIntNestedLeft();
102 40
        $right = $root->GetIntNestedRight();
103 40
        $limit = is_int($limit) ? ($root->GetIntNestedLevel() + $limit) : null;
104
105 40
        $leaves = $this->RecallDaftNestedObjectFullTree();
106
107 40
        if (is_int($limit)) {
108
            $leaves = array_filter($leaves, function (DaftNestedObject $e) use ($limit) : bool {
109 38
                return $e->GetIntNestedLevel() <= $limit;
110 38
            });
111
        }
112
113 40
        return array_values(array_filter(
114 40
            $leaves,
115
            /**
116
            * @psalm-param T $e
117
            */
118
            function (DaftNestedObject $e) use ($includeRoot, $left, $right) : bool {
119 40
                return $this->FilterLeaf($includeRoot, $left, $right, $e);
120 40
            }
121
        ));
122
    }
123
124
    /**
125
    * @psalm-param T $root
126
    */
127 12
    public function CountDaftNestedObjectTreeWithObject(
128
        DaftNestedObject $root,
129
        bool $includeRoot,
130
        ? int $relativeDepthLimit
131
    ) : int {
132 12
        return count(
133 12
            $this->RecallDaftNestedObjectTreeWithObject($root, $includeRoot, $relativeDepthLimit)
134
        );
135
    }
136
137
    /**
138
    * @param scalar|(scalar|array|object|null)[] $id
139
    *
140
    * @return array<int, DaftNestedObject>
141
    *
142
    * @psalm-return array<int, T>
143
    */
144 56
    public function RecallDaftNestedObjectTreeWithId(
145
        $id,
146
        bool $includeRoot,
147
        ? int $relativeDepthLimit
148
    ) : array {
149 56
        $object = $this->RecallDaftObject($id);
150
151
        /**
152
        * @var array<int, DaftNestedObject>
153
        *
154
        * @psalm-var array<int, T>
155
        */
156
        $out =
157 56
            ($object instanceof DaftNestedObject)
158 28
                ? $this->RecallDaftNestedObjectTreeWithObject(
159 28
                    $object,
160 28
                    $includeRoot,
161 28
                    $relativeDepthLimit
162
                )
163
                : (
164 32
                    ((array) $id === $this->GetNestedObjectTreeRootId())
165 32
                        ? $this->RecallDaftNestedObjectFullTree($relativeDepthLimit)
166 56
                        : []
167
                );
168
169 56
        return $out;
170
    }
171
172
    /**
173
    * @param scalar|(scalar|array|object|null)[] $id
174
    */
175 4
    public function CountDaftNestedObjectTreeWithId(
176
        $id,
177
        bool $includeRoot,
178
        ? int $relativeDepthLimit
179
    ) : int {
180 4
        return count($this->RecallDaftNestedObjectTreeWithId(
181 4
            $id,
182 4
            $includeRoot,
183 4
            $relativeDepthLimit
184
        ));
185
    }
186
187
    /**
188
    * @psalm-param T $leaf
189
    *
190
    * @return array<int, DaftNestedObject>
191
    *
192
    * @psalm-return array<int, T>
193
    */
194 4
    public function RecallDaftNestedObjectPathToObject(
195
        DaftNestedObject $leaf,
196
        bool $includeLeaf
197
    ) : array {
198
        $left =
199 4
            $leaf->GetIntNestedLeft() +
200 4
            ($includeLeaf ? self::BOOL_DEFAULT_NO_MODIFY : self::DECREMENT);
201
        $right =
202 4
            $leaf->GetIntNestedRight() +
203 4
            ($includeLeaf ? self::BOOL_DEFAULT_NO_MODIFY : self::INCREMENT);
204
205
        /**
206
        * @var array<int, DaftNestedObject>
207
        *
208
        * @psalm-var array<int, T>
209
        */
210 4
        $out = array_values(array_filter(
211 4
            $this->RecallDaftNestedObjectFullTree(),
212
            function (DaftNestedObject $e) use ($left, $right) : bool {
213 4
                return $e->GetIntNestedLeft() <= $left && $e->GetIntNestedRight() >= $right;
214 4
            }
215
        ));
216
217 4
        return $out;
218
    }
219
220
    /**
221
    * @psalm-param T $leaf
222
    */
223 4
    public function CountDaftNestedObjectPathToObject(
224
        DaftNestedObject $leaf,
225
        bool $includeLeaf
226
    ) : int {
227 4
        return count($this->RecallDaftNestedObjectPathToObject($leaf, $includeLeaf));
228
    }
229
230
    /**
231
    * @param scalar|(scalar|array|object|null)[] $id
232
    *
233
    * @return array<int, DaftNestedObject>
234
    *
235
    * @psalm-return array<int, T>
236
    */
237 4
    public function RecallDaftNestedObjectPathToId($id, bool $includeLeaf) : array
238
    {
239
        /**
240
        * @var DaftNestedObject|null
241
        *
242
        * @psalm-var T|null
243
        */
244 4
        $object = $this->RecallDaftObject($id);
245
246
        /**
247
        * @var array<int, DaftNestedObject>
248
        *
249
        * @psalm-var array<int, T>
250
        */
251
        $out =
252 4
            ($object instanceof DaftNestedObject)
253 4
                ? $this->RecallDaftNestedObjectPathToObject($object, $includeLeaf)
254 4
                : [];
255
256 4
        return $out;
257
    }
258
259
    /**
260
    * @param scalar|(scalar|array|object|null)[] $id
261
    */
262 4
    public function CountDaftNestedObjectPathToId($id, bool $includeLeaf) : int
263
    {
264 4
        return count($this->RecallDaftNestedObjectPathToId($id, $includeLeaf));
265
    }
266
267
    /**
268
    * @psalm-param T $object
269
    */
270 92
    public function RememberDaftObject(SuitableForRepositoryType $object) : void
271
    {
272 92
        parent::RememberDaftObject($object);
273 92
    }
274
275
    /**
276
    * {@inheritdoc}
277
    *
278
    * @psalm-return T|null
279
    */
280 66
    public function RecallDaftObject($id) : ? SuitableForRepositoryType
281
    {
282
        /**
283
        * @psalm-var T|null
284
        */
285 66
        $out = parent::RecallDaftObject($id);
286
287 66
        return $out;
288
    }
289
290
    /**
291
    * @psalm-return T
292
    */
293 64
    private function MapDataToObject(array $row) : DaftNestedObject
294
    {
295 64
        $type = $this->type;
296
297
        /**
298
        * @var DaftNestedObject
299
        *
300
        * @psalm-var T
301
        */
302 64
        $out = new $type($row);
303
304 64
        return $out;
305
    }
306
307
    /**
308
    * @psalm-param T $e
309
    */
310 40
    private function FilterLeaf(
311
        bool $includeRoot,
312
        int $left,
313
        int $right,
314
        DaftNestedObject $e
315
    ) : bool {
316 40
        if ($includeRoot) {
317 4
            return $e->GetIntNestedLeft() >= $left && $e->GetIntNestedRight() <= $right;
318
        }
319
320 40
        return $e->GetIntNestedLeft() > $left && $e->GetIntNestedRight() < $right;
321
    }
322
}
323