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 BadMethodCallException; |
||||||
12 | use InvalidArgumentException; |
||||||
13 | use RuntimeException; |
||||||
14 | |||||||
15 | /** |
||||||
16 | * @template T as DaftNestedWriteableObject |
||||||
17 | */ |
||||||
18 | trait WriteableTreeTrait |
||||||
19 | { |
||||||
20 | /** |
||||||
21 | * @psalm-param T $root |
||||||
22 | */ |
||||||
23 | abstract public function CountDaftNestedObjectTreeWithObject( |
||||||
24 | DaftNestedObject $root, |
||||||
25 | bool $includeRoot, |
||||||
26 | ? int $relativeDepthLimit |
||||||
27 | ) : int; |
||||||
28 | |||||||
29 | abstract public function RemoveDaftObject(SuitableForRepositoryType $object) : void; |
||||||
30 | |||||||
31 | /** |
||||||
32 | * @param scalar|(scalar|array|object|null)[] $id |
||||||
33 | * |
||||||
34 | * @psalm-return T|null |
||||||
35 | */ |
||||||
36 | abstract public function RecallDaftObject($id) : ? SuitableForRepositoryType; |
||||||
37 | |||||||
38 | abstract public function ForgetDaftObject(SuitableForRepositoryType $object) : void; |
||||||
39 | |||||||
40 | /** |
||||||
41 | * @param scalar|(scalar|array|object|null)[] $id |
||||||
42 | */ |
||||||
43 | abstract public function ForgetDaftObjectById($id) : void; |
||||||
44 | |||||||
45 | /** |
||||||
46 | * @return array<int, DaftNestedObject> |
||||||
47 | * |
||||||
48 | * @psalm-return array<int, T> |
||||||
49 | */ |
||||||
50 | abstract public function RecallDaftNestedObjectFullTree(int $relativeDepthLimit = null) : array; |
||||||
51 | |||||||
52 | /** |
||||||
53 | * @psalm-param T $root |
||||||
54 | * |
||||||
55 | * @return array<int, DaftNestedObject> |
||||||
56 | * |
||||||
57 | * @psalm-return array<int, T> |
||||||
58 | */ |
||||||
59 | abstract public function RecallDaftNestedObjectTreeWithObject( |
||||||
60 | DaftNestedObject $root, |
||||||
61 | bool $includeRoot, |
||||||
62 | ? int $relativeDepthLimit |
||||||
63 | ) : array; |
||||||
64 | |||||||
65 | /** |
||||||
66 | * @return scalar[] |
||||||
67 | */ |
||||||
68 | abstract public function GetNestedObjectTreeRootId() : array; |
||||||
69 | |||||||
70 | /** |
||||||
71 | * @param scalar|(scalar|array|object|null)[] $id |
||||||
72 | * |
||||||
73 | * @return array<int, DaftNestedObject> |
||||||
74 | * |
||||||
75 | * @psalm-return array<int, T> |
||||||
76 | */ |
||||||
77 | abstract public function RecallDaftNestedObjectTreeWithId( |
||||||
78 | $id, |
||||||
79 | bool $includeRoot, |
||||||
80 | ? int $relativeDepthLimit |
||||||
81 | ) : array; |
||||||
82 | |||||||
83 | abstract public function CountDaftNestedObjectFullTree(int $relativeDepthLimit = null) : int; |
||||||
84 | |||||||
85 | /** |
||||||
86 | * {@inheritdoc} |
||||||
87 | * |
||||||
88 | * @psalm-param class-string<T> $type |
||||||
89 | * |
||||||
90 | * @psalm-return T |
||||||
91 | */ |
||||||
92 | abstract public function RecallDaftObjectOrThrow( |
||||||
93 | $id, |
||||||
94 | string $type = DaftNestedObject::class |
||||||
95 | ) : SuitableForRepositoryType; |
||||||
96 | |||||||
97 | /** |
||||||
98 | * @psalm-param T $newLeaf |
||||||
99 | * @psalm-param T $referenceLeaf |
||||||
100 | * |
||||||
101 | * @psalm-return T |
||||||
102 | */ |
||||||
103 | 84 | public function ModifyDaftNestedObjectTreeInsert( |
|||||
104 | DaftNestedWriteableObject $newLeaf, |
||||||
105 | DaftNestedWriteableObject $referenceLeaf, |
||||||
106 | bool $before = DaftNestedWriteableObjectTree::INSERT_AFTER, |
||||||
107 | bool $above = null |
||||||
108 | ) : DaftNestedWriteableObject { |
||||||
109 | 84 | if ($newLeaf->GetId() === $referenceLeaf->GetId()) { |
|||||
110 | 40 | throw new InvalidArgumentException('Cannot modify leaf relative to itself!'); |
|||||
111 | } |
||||||
112 | |||||||
113 | 60 | if ((bool) $above) { |
|||||
114 | 48 | $this->ModifyDaftNestedObjectTreeInsertAbove($newLeaf, $referenceLeaf); |
|||||
115 | 32 | } elseif (DaftNestedWriteableObjectTree::DEFINITELY_BELOW === $above) { |
|||||
116 | 6 | $this->ModifyDaftNestedObjectTreeInsertBelow($newLeaf, $referenceLeaf); |
|||||
117 | } else { |
||||||
118 | 28 | $this->ModifyDaftNestedObjectTreeInsertAdjacent($newLeaf, $referenceLeaf, $before); |
|||||
119 | } |
||||||
120 | |||||||
121 | 60 | return $this->RebuildAfterInsert($newLeaf); |
|||||
122 | } |
||||||
123 | |||||||
124 | /** |
||||||
125 | * @param DaftNestedWriteableObject|scalar|(scalar|array|object|null)[] $leaf |
||||||
126 | * @param DaftNestedWriteableObject|scalar|(scalar|array|object|null)[] $referenceId |
||||||
127 | * |
||||||
128 | * @psalm-param T|scalar|(scalar|array|object|null)[] $leaf |
||||||
129 | * @psalm-param T|scalar|(scalar|array|object|null)[] $referenceId |
||||||
130 | * |
||||||
131 | * @psalm-return T |
||||||
132 | */ |
||||||
133 | 48 | public function ModifyDaftNestedObjectTreeInsertLoose( |
|||||
134 | $leaf, |
||||||
135 | $referenceId, |
||||||
136 | bool $before = DaftNestedWriteableObjectTree::INSERT_AFTER, |
||||||
137 | bool $above = null |
||||||
138 | ) : DaftNestedWriteableObject { |
||||||
139 | /** |
||||||
140 | * @var DaftNestedWriteableObject |
||||||
141 | * |
||||||
142 | * @psalm-var T |
||||||
143 | */ |
||||||
144 | 48 | $leaf = $this->MaybeGetLeafOrThrow($leaf); |
|||||
145 | |||||||
146 | 24 | $reference = $this->MaybeRecallLoose($referenceId); |
|||||
147 | |||||||
148 | 24 | if ( ! is_null($reference)) { |
|||||
149 | 18 | return $this->ModifyDaftNestedObjectTreeInsert($leaf, $reference, $before, $above); |
|||||
150 | } |
||||||
151 | |||||||
152 | 24 | return $this->ModifyDaftNestedObjectTreeInsertLooseIntoTree($leaf, $before, $above); |
|||||
153 | } |
||||||
154 | |||||||
155 | /** |
||||||
156 | * @psalm-param T $root |
||||||
157 | * @psalm-param T|null $replacementRoot |
||||||
158 | */ |
||||||
159 | 8 | public function ModifyDaftNestedObjectTreeRemoveWithObject( |
|||||
160 | DaftNestedWriteableObject $root, |
||||||
161 | ? DaftNestedWriteableObject $replacementRoot |
||||||
162 | ) : int { |
||||||
163 | if ( |
||||||
164 | 8 | $this->CountDaftNestedObjectTreeWithObject( |
|||||
165 | 8 | $root, |
|||||
166 | 8 | false, |
|||||
167 | 8 | null |
|||||
168 | 8 | ) > AbstractArrayBackedDaftNestedObject::COUNT_EXPECT_NON_EMPTY && |
|||||
169 | 8 | is_null($replacementRoot) |
|||||
170 | ) { |
||||||
171 | 2 | throw new BadMethodCallException('Cannot leave orphan objects in a tree'); |
|||||
172 | } |
||||||
173 | |||||||
174 | 6 | $root = $this->StoreThenRetrieveFreshLeaf($root); |
|||||
175 | |||||||
176 | 6 | if ( ! is_null($replacementRoot)) { |
|||||
177 | 4 | $this->UpdateRoots( |
|||||
178 | 4 | $root, |
|||||
179 | 4 | (array) $this->StoreThenRetrieveFreshLeaf($replacementRoot)->GetId() |
|||||
180 | ); |
||||||
181 | } |
||||||
182 | |||||||
183 | 6 | $this->RemoveDaftObject($root); |
|||||
184 | |||||||
185 | 6 | $this->RebuildTreeInefficiently(); |
|||||
186 | |||||||
187 | 6 | return $this->CountDaftNestedObjectFullTree(); |
|||||
188 | } |
||||||
189 | |||||||
190 | /** |
||||||
191 | * @param scalar[] $root |
||||||
192 | * @param scalar[] $replacementRoot |
||||||
193 | */ |
||||||
194 | 12 | public function ModifyDaftNestedObjectTreeRemoveWithId( |
|||||
195 | array $root, |
||||||
196 | array $replacementRoot |
||||||
197 | ) : int { |
||||||
198 | 12 | $rootObject = $this->RecallDaftObject($root); |
|||||
199 | |||||||
200 | 12 | $resp = null; |
|||||
201 | |||||||
202 | 12 | if ($rootObject instanceof DaftNestedWriteableObject) { |
|||||
203 | 12 | $resp = $this->ModifyDaftNestedObjectTreeRemoveWithIdUsingRootObject( |
|||||
204 | 12 | $replacementRoot, |
|||||
205 | 12 | $rootObject |
|||||
206 | ); |
||||||
207 | } |
||||||
208 | |||||||
209 | 8 | return is_int($resp) ? $resp : $this->CountDaftNestedObjectFullTree(); |
|||||
210 | } |
||||||
211 | |||||||
212 | /** |
||||||
213 | * @psalm-param T $leaf |
||||||
214 | * |
||||||
215 | * @psalm-return T |
||||||
216 | */ |
||||||
217 | 62 | public function StoreThenRetrieveFreshLeaf( |
|||||
218 | DaftNestedWriteableObject $leaf |
||||||
219 | ) : DaftNestedWriteableObject { |
||||||
220 | 62 | $this->RememberDaftObject($leaf); |
|||||
221 | 62 | $this->ForgetDaftObject($leaf); |
|||||
222 | 62 | $this->ForgetDaftObjectById($leaf->GetId()); |
|||||
223 | |||||||
224 | /** |
||||||
225 | * @psalm-var class-string<T> |
||||||
226 | */ |
||||||
227 | 62 | $type = get_class($leaf); |
|||||
228 | |||||||
229 | /** |
||||||
230 | * @var DaftNestedWriteableObject |
||||||
231 | * |
||||||
232 | * @psalm-var T |
||||||
233 | */ |
||||||
234 | 62 | $out = $this->RecallDaftObjectOrThrow($leaf->GetId(), $type); |
|||||
235 | |||||||
236 | 60 | return $out; |
|||||
0 ignored issues
–
show
Bug
Best Practice
introduced
by
![]() |
|||||||
237 | } |
||||||
238 | |||||||
239 | /** |
||||||
240 | * @psalm-param T $object |
||||||
241 | */ |
||||||
242 | 90 | public function RememberDaftObject(SuitableForRepositoryType $object) : void |
|||||
243 | { |
||||||
244 | /** |
||||||
245 | * @var DaftNestedWriteableObject |
||||||
246 | * |
||||||
247 | * @psalm-var T |
||||||
248 | */ |
||||||
249 | 90 | $object = $object; |
|||||
250 | |||||||
251 | 90 | if (NestedTypeParanoia::NotYetAppendedToTree($object)) { |
|||||
252 | 86 | $fullTreeCount = $this->CountDaftNestedObjectFullTree(); |
|||||
253 | |||||||
254 | 86 | if ($fullTreeCount > AbstractArrayBackedDaftNestedObject::COUNT_EXPECT_NON_EMPTY) { |
|||||
255 | 60 | $end = $this->ObtainLastLeafInTree(); |
|||||
256 | |||||||
257 | 60 | $left = $end->GetIntNestedRight() + 1; |
|||||
258 | } else { |
||||||
259 | 86 | $left = $fullTreeCount + $fullTreeCount; |
|||||
260 | } |
||||||
261 | |||||||
262 | 86 | $object->SetIntNestedLeft($left); |
|||||
0 ignored issues
–
show
The method
SetIntNestedLeft() does not exist on SignpostMarv\DaftObject\SuitableForRepositoryType . It seems like you code against a sub-type of SignpostMarv\DaftObject\SuitableForRepositoryType such as SignpostMarv\DaftObject\DaftNestedWriteableObject or SignpostMarv\DaftObject\...estedWriteableIntObject .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
263 | 86 | $object->SetIntNestedRight($left + 1); |
|||||
0 ignored issues
–
show
The method
SetIntNestedRight() does not exist on SignpostMarv\DaftObject\SuitableForRepositoryType . It seems like you code against a sub-type of SignpostMarv\DaftObject\SuitableForRepositoryType such as SignpostMarv\DaftObject\DaftNestedWriteableObject or SignpostMarv\DaftObject\...estedWriteableIntObject .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
264 | } |
||||||
265 | |||||||
266 | 90 | parent::RememberDaftObject($object); |
|||||
267 | 90 | } |
|||||
268 | |||||||
269 | /** |
||||||
270 | * @psalm-return T |
||||||
271 | */ |
||||||
272 | abstract protected function ObtainLastLeafInTree() : DaftNestedWriteableObject; |
||||||
273 | |||||||
274 | /** |
||||||
275 | * @psalm-param T $newLeaf |
||||||
276 | * @psalm-param T $referenceLeaf |
||||||
277 | */ |
||||||
278 | 52 | protected function ModifyDaftNestedObjectTreeInsertAdjacent( |
|||||
279 | DaftNestedWriteableObject $newLeaf, |
||||||
280 | DaftNestedWriteableObject $referenceLeaf, |
||||||
281 | bool $before |
||||||
282 | ) : void { |
||||||
283 | 52 | $siblings = $this->SiblingsExceptLeaf($newLeaf, $referenceLeaf); |
|||||
284 | |||||||
285 | 52 | $siblingIds = []; |
|||||
286 | 52 | $siblingSort = []; |
|||||
287 | 52 | $j = count($siblings); |
|||||
288 | |||||||
289 | 52 | foreach ($siblings as $leaf) { |
|||||
290 | /** |
||||||
291 | * @var scalar|(scalar|array|object|null)[] |
||||||
292 | */ |
||||||
293 | 28 | $siblingId = $leaf->GetId(); |
|||||
294 | 28 | $siblingIds[] = $siblingId; |
|||||
295 | 28 | $siblingSort[] = $leaf->GetIntNestedSortOrder(); |
|||||
296 | } |
||||||
297 | |||||||
298 | 52 | $pos = array_search($referenceLeaf->GetId(), $siblingIds, true); |
|||||
299 | |||||||
300 | 52 | if (false === $pos) { |
|||||
301 | 24 | throw new RuntimeException('Reference leaf not found in siblings tree!'); |
|||||
302 | } |
||||||
303 | |||||||
304 | 28 | for ($i = 0; $i < $j; ++$i) { |
|||||
305 | 28 | $siblings[$i]->SetIntNestedSortOrder( |
|||||
306 | 28 | $siblingSort[$i] + |
|||||
307 | 28 | (($before ? ($i < $pos) : ($i <= $pos)) ? DaftNestedObjectTree::DECREMENT : DaftNestedObjectTree::INCREMENT) |
|||||
308 | ); |
||||||
309 | 28 | $this->StoreThenRetrieveFreshLeaf($siblings[$i]); |
|||||
310 | } |
||||||
311 | |||||||
312 | 28 | $newLeaf->SetIntNestedSortOrder($siblingSort[$pos]); |
|||||
313 | 28 | $newLeaf->SetDaftNestedObjectParentId($referenceLeaf->GetDaftNestedObjectParentId()); |
|||||
314 | |||||||
315 | 28 | $this->StoreThenRetrieveFreshLeaf($newLeaf); |
|||||
316 | 28 | } |
|||||
317 | |||||||
318 | 60 | protected function RebuildTreeInefficiently() : void |
|||||
319 | { |
||||||
320 | 60 | $rebuilder = new InefficientDaftNestedRebuild($this); |
|||||
0 ignored issues
–
show
$this of type SignpostMarv\DaftObject\WriteableTreeTrait is incompatible with the type SignpostMarv\DaftObject\...stedWriteableObjectTree expected by parameter $tree of SignpostMarv\DaftObject\...dRebuild::__construct() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
321 | 60 | $rebuilder->RebuildTree(); |
|||||
322 | 60 | } |
|||||
323 | |||||||
324 | /** |
||||||
325 | * @psalm-param T $newLeaf |
||||||
326 | * |
||||||
327 | * @psalm-return T |
||||||
328 | */ |
||||||
329 | 60 | private function RebuildAfterInsert( |
|||||
330 | DaftNestedWriteableObject $newLeaf |
||||||
331 | ) : DaftNestedWriteableObject { |
||||||
332 | 60 | $this->RebuildTreeInefficiently(); |
|||||
333 | |||||||
334 | /** |
||||||
335 | * @psalm-var class-string<T> |
||||||
336 | */ |
||||||
337 | 60 | $type = get_class($newLeaf); |
|||||
338 | |||||||
339 | /** |
||||||
340 | * @var DaftNestedWriteableObject |
||||||
341 | * |
||||||
342 | * @psalm-var T |
||||||
343 | */ |
||||||
344 | 60 | $out = $this->RecallDaftObjectOrThrow($newLeaf->GetId(), $type); |
|||||
345 | |||||||
346 | 48 | return $out; |
|||||
0 ignored issues
–
show
|
|||||||
347 | } |
||||||
348 | |||||||
349 | /** |
||||||
350 | * @param scalar[] $replacementRootId |
||||||
351 | * |
||||||
352 | * @psalm-param T $root |
||||||
353 | */ |
||||||
354 | 10 | private function UpdateRoots(DaftNestedWriteableObject $root, array $replacementRootId) : void |
|||||
355 | { |
||||||
356 | /** |
||||||
357 | * @var array<int, DaftNestedWriteableObject> |
||||||
358 | * |
||||||
359 | * @psalm-var array<int, T> |
||||||
360 | */ |
||||||
361 | 10 | $alterThese = $this->RecallDaftNestedObjectTreeWithObject($root, false, DaftNestedWriteableObjectTree::LIMIT_ONE); |
|||||
362 | |||||||
363 | 10 | foreach ($alterThese as $alter) { |
|||||
364 | 4 | $alter->SetDaftNestedObjectParentId($replacementRootId); |
|||||
365 | 4 | $this->RememberDaftObject($alter); |
|||||
366 | } |
||||||
367 | 10 | } |
|||||
368 | |||||||
369 | /** |
||||||
370 | * @param DaftNestedWriteableObject|scalar|(scalar|array|object|null)[] $leaf |
||||||
371 | * |
||||||
372 | * @psalm-param T|scalar|(scalar|array|object|null)[] $leaf |
||||||
373 | * @psalm-param class-string<T> $type |
||||||
374 | * |
||||||
375 | * @psalm-return T |
||||||
376 | */ |
||||||
377 | 48 | private function MaybeGetLeafOrThrow( |
|||||
378 | $leaf, |
||||||
379 | string $type = DaftNestedWriteableObject::class |
||||||
380 | ) : DaftNestedWriteableObject { |
||||||
381 | 48 | if ($leaf === $this->GetNestedObjectTreeRootId()) { |
|||||
382 | 24 | throw new InvalidArgumentException('Cannot pass root id as new leaf'); |
|||||
383 | 24 | } elseif ($leaf instanceof DaftNestedWriteableObject) { |
|||||
384 | 24 | return $this->StoreThenRetrieveFreshLeaf($leaf); |
|||||
385 | } |
||||||
386 | |||||||
387 | /** |
||||||
388 | * @psalm-var scalar|(scalar|array|object|null)[] |
||||||
389 | */ |
||||||
390 | 16 | $leaf = $leaf; |
|||||
391 | |||||||
392 | /** |
||||||
393 | * @var DaftNestedWriteableObject |
||||||
394 | * |
||||||
395 | * @psalm-var T |
||||||
396 | */ |
||||||
397 | 16 | $out = $this->RecallDaftObjectOrThrow($leaf, $type); |
|||||
398 | |||||||
399 | 16 | return $out; |
|||||
0 ignored issues
–
show
|
|||||||
400 | } |
||||||
401 | |||||||
402 | /** |
||||||
403 | * @param DaftNestedWriteableObject|scalar|(scalar|array|object|null)[] $leaf |
||||||
404 | * |
||||||
405 | * @psalm-param T|scalar|(scalar|array|object|null)[] $leaf |
||||||
406 | */ |
||||||
407 | 24 | private function MaybeRecallLoose($leaf) : ? DaftNestedWriteableObject |
|||||
408 | { |
||||||
409 | 24 | if ($leaf instanceof DaftNestedWriteableObject) { |
|||||
410 | 2 | return $leaf; |
|||||
411 | } |
||||||
412 | |||||||
413 | /** |
||||||
414 | * @var scalar|(scalar|array|object|null)[] |
||||||
415 | */ |
||||||
416 | 24 | $leaf = $leaf; |
|||||
417 | |||||||
418 | /** |
||||||
419 | * @var DaftNestedWriteableObject|null |
||||||
420 | * |
||||||
421 | * @psalm-var T|null |
||||||
422 | */ |
||||||
423 | 24 | $out = $this->RecallDaftObject($leaf); |
|||||
424 | |||||||
425 | 24 | return $out; |
|||||
0 ignored issues
–
show
|
|||||||
426 | } |
||||||
427 | |||||||
428 | /** |
||||||
429 | * @psalm-param T $leaf |
||||||
430 | * |
||||||
431 | * @psalm-return T |
||||||
432 | */ |
||||||
433 | 24 | private function ModifyDaftNestedObjectTreeInsertLooseIntoTree( |
|||||
434 | DaftNestedWriteableObject $leaf, |
||||||
435 | bool $before, |
||||||
436 | ? bool $above |
||||||
437 | ) : DaftNestedWriteableObject { |
||||||
438 | /** |
||||||
439 | * @var array<int, DaftNestedWriteableObject> |
||||||
440 | * |
||||||
441 | * @psalm-var array<int, T> |
||||||
442 | */ |
||||||
443 | 24 | $leaves = array_filter( |
|||||
444 | 24 | $this->RecallDaftNestedObjectFullTree(DaftNestedWriteableObjectTree::RELATIVE_DEPTH_SAME), |
|||||
445 | /** |
||||||
446 | * @psalm-param T $e |
||||||
447 | */ |
||||||
448 | function (DaftNestedWriteableObject $e) use ($leaf) : bool { |
||||||
449 | 24 | return $e->GetId() !== $leaf->GetId(); |
|||||
450 | 24 | } |
|||||
451 | ); |
||||||
452 | |||||||
453 | 24 | if (count($leaves) < 1) { |
|||||
454 | 24 | $leaf->SetIntNestedLeft(0); |
|||||
455 | 24 | $leaf->SetIntNestedRight(1); |
|||||
456 | 24 | $leaf->SetIntNestedLevel(0); |
|||||
457 | 24 | $leaf->SetDaftNestedObjectParentId($this->GetNestedObjectTreeRootId()); |
|||||
458 | |||||||
459 | 24 | return $this->StoreThenRetrieveFreshLeaf($leaf); |
|||||
460 | } |
||||||
461 | |||||||
462 | 24 | return $this->ModifyDaftNestedObjectTreeInsert( |
|||||
463 | 24 | $leaf, |
|||||
464 | 24 | NestedTypeParanoia::ObtainFirstOrLast($before, ...$leaves), |
|||||
465 | 24 | $before, |
|||||
466 | 24 | $above |
|||||
467 | ); |
||||||
468 | } |
||||||
469 | |||||||
470 | /** |
||||||
471 | * @psalm-param T $newLeaf |
||||||
472 | * @psalm-param T $referenceLeaf |
||||||
473 | */ |
||||||
474 | 48 | private function ModifyDaftNestedObjectTreeInsertAbove( |
|||||
475 | DaftNestedWriteableObject $newLeaf, |
||||||
476 | DaftNestedWriteableObject $referenceLeaf |
||||||
477 | ) : void { |
||||||
478 | 48 | $newLeaf->SetDaftNestedObjectParentId($referenceLeaf->GetDaftNestedObjectParentId()); |
|||||
479 | 48 | $referenceLeaf->SetDaftNestedObjectParentId((array) $newLeaf->GetId()); |
|||||
480 | |||||||
481 | 48 | $this->StoreThenRetrieveFreshLeaf($newLeaf); |
|||||
482 | 48 | $this->StoreThenRetrieveFreshLeaf($referenceLeaf); |
|||||
483 | 48 | } |
|||||
484 | |||||||
485 | /** |
||||||
486 | * @psalm-param T $newLeaf |
||||||
487 | * @psalm-param T $referenceLeaf |
||||||
488 | */ |
||||||
489 | 6 | private function ModifyDaftNestedObjectTreeInsertBelow( |
|||||
490 | DaftNestedWriteableObject $newLeaf, |
||||||
491 | DaftNestedWriteableObject $referenceLeaf |
||||||
492 | ) : void { |
||||||
493 | 6 | $newLeaf->SetDaftNestedObjectParentId((array) $referenceLeaf->GetId()); |
|||||
494 | 6 | $this->StoreThenRetrieveFreshLeaf($newLeaf); |
|||||
495 | 6 | } |
|||||
496 | |||||||
497 | /** |
||||||
498 | * @psalm-param T $newLeaf |
||||||
499 | * @psalm-param T $referenceLeaf |
||||||
500 | * |
||||||
501 | * @return array<int, DaftNestedWriteableObject> |
||||||
502 | * |
||||||
503 | * @psalm-return array<int, T> |
||||||
504 | */ |
||||||
505 | 52 | private function SiblingsExceptLeaf( |
|||||
506 | DaftNestedWriteableObject $newLeaf, |
||||||
507 | DaftNestedWriteableObject $referenceLeaf |
||||||
508 | ) : array { |
||||||
509 | /** |
||||||
510 | * @var array<int, DaftNestedWriteableObject> |
||||||
511 | * |
||||||
512 | * @psalm-var array<int, T> |
||||||
513 | */ |
||||||
514 | 52 | $out = array_values(array_filter( |
|||||
515 | 52 | $this->RecallDaftNestedObjectTreeWithId( |
|||||
516 | 52 | $referenceLeaf->GetDaftNestedObjectParentId(), |
|||||
517 | 52 | DaftNestedWriteableObjectTree::EXCLUDE_ROOT, |
|||||
518 | 52 | DaftNestedWriteableObjectTree::RELATIVE_DEPTH_SAME |
|||||
519 | ), |
||||||
520 | /** |
||||||
521 | * @psalm-param T $leaf |
||||||
522 | */ |
||||||
523 | function (DaftNestedWriteableObject $leaf) use ($newLeaf) : bool { |
||||||
524 | 28 | return $leaf->GetId() !== $newLeaf->GetId(); |
|||||
525 | 52 | } |
|||||
526 | )); |
||||||
527 | |||||||
528 | 52 | return $out; |
|||||
529 | } |
||||||
530 | |||||||
531 | /** |
||||||
532 | * @param scalar[] $replacementRoot |
||||||
533 | * |
||||||
534 | * @psalm-param T $rootObject |
||||||
535 | */ |
||||||
536 | 12 | private function ModifyDaftNestedObjectTreeRemoveWithIdUsingRootObject( |
|||||
537 | array $replacementRoot, |
||||||
538 | DaftNestedWriteableObject $rootObject |
||||||
539 | ) : ? int { |
||||||
540 | if ( |
||||||
541 | 12 | $replacementRoot !== $this->GetNestedObjectTreeRootId() |
|||||
542 | ) { |
||||||
543 | /** |
||||||
544 | * @psalm-var class-string<T> |
||||||
545 | */ |
||||||
546 | 6 | $type = get_class($rootObject); |
|||||
547 | |||||||
548 | /** |
||||||
549 | * @var DaftNestedWriteableObject |
||||||
550 | * |
||||||
551 | * @psalm-var T |
||||||
552 | */ |
||||||
553 | 6 | $replacement = $this->RecallDaftObjectOrThrow($replacementRoot, $type); |
|||||
554 | |||||||
555 | 2 | return $this->ModifyDaftNestedObjectTreeRemoveWithObject( |
|||||
556 | 2 | $rootObject, |
|||||
557 | 2 | $replacement |
|||||
558 | ); |
||||||
559 | } |
||||||
560 | |||||||
561 | 6 | $this->UpdateRoots($rootObject, $replacementRoot); |
|||||
562 | |||||||
563 | 6 | $this->RemoveDaftObject($rootObject); |
|||||
564 | |||||||
565 | 6 | $this->RebuildTreeInefficiently(); |
|||||
566 | |||||||
567 | 6 | return null; |
|||||
568 | } |
||||||
569 | } |
||||||
570 |