Passed
Push — master ( e625f3...d66cf7 )
by SignpostMarv
02:37
created

RecallDaftNestedObjectPathToObject()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 16
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3

Importance

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