Test Failed
Push — master ( 7826a3...f27fcf )
by SignpostMarv
06:31
created

DaftObjectMemoryTree::RememberDaftObjectData()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 1

Importance

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