Passed
Push — master ( d3ba44...b8f1e8 )
by SignpostMarv
06:46
created

RecallDaftNestedObjectPathToId()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

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