Passed
Push — master ( be1c18...95b62e )
by SignpostMarv
05:53
created

DaftWriteableObjectMemoryTree::MaybeGetLeaf()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 21
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 7
nc 3
nop 1
dl 0
loc 21
ccs 8
cts 8
cp 1
crap 3
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 BadMethodCallException;
12
use InvalidArgumentException;
13
use RuntimeException;
14
15
/**
16
* @template T as DaftNestedWriteableObject
17
*
18
* @template-extends DaftObjectMemoryTree<T>
19
*
20
* @template-implements DaftNestedWriteableObjectTree<T>
21
*/
22
abstract class DaftWriteableObjectMemoryTree extends DaftObjectMemoryTree implements DaftNestedWriteableObjectTree
23
{
24
    const DEFINITELY_BELOW = false;
25
26
    const EXCLUDE_ROOT = false;
27
28
    const INSERT_AFTER = false;
29
30
    const LIMIT_ONE = 1;
31
32
    const RELATIVE_DEPTH_SAME = 0;
33
34
    const INT_ARG_INDEX_SECOND = 2;
35
36
    /**
37
    * @psalm-param T $newLeaf
38
    * @psalm-param T $referenceLeaf
39
    *
40
    * @psalm-return T
41
    */
42 84
    public function ModifyDaftNestedObjectTreeInsert(
43
        DaftNestedWriteableObject $newLeaf,
44
        DaftNestedWriteableObject $referenceLeaf,
45
        bool $before = self::INSERT_AFTER,
46
        bool $above = null
47
    ) : DaftNestedWriteableObject {
48 84
        if ($newLeaf->GetId() === $referenceLeaf->GetId()) {
49 40
            throw new InvalidArgumentException('Cannot modify leaf relative to itself!');
50
        }
51
52 60
        if ((bool) $above) {
53 48
            $this->ModifyDaftNestedObjectTreeInsertAbove($newLeaf, $referenceLeaf);
54 32
        } elseif (self::DEFINITELY_BELOW === $above) {
55 6
            $this->ModifyDaftNestedObjectTreeInsertBelow($newLeaf, $referenceLeaf);
56
        } else {
57 28
            $this->ModifyDaftNestedObjectTreeInsertAdjacent($newLeaf, $referenceLeaf, $before);
58
        }
59
60 60
        return $this->RebuildAfterInsert($newLeaf);
61
    }
62
63
    /**
64
    * @param DaftNestedWriteableObject|scalar|(scalar|array|object|null)[] $leaf
65
    * @param DaftNestedWriteableObject|scalar|(scalar|array|object|null)[] $referenceId
66
    *
67
    * @psalm-param T|scalar|(scalar|array|object|null)[] $leaf
68
    * @psalm-param T|scalar|(scalar|array|object|null)[] $referenceId
69
    *
70
    * @psalm-return T
71
    */
72 48
    public function ModifyDaftNestedObjectTreeInsertLoose(
73
        $leaf,
74
        $referenceId,
75
        bool $before = self::INSERT_AFTER,
76
        bool $above = null
77
    ) : DaftNestedWriteableObject {
78 48
        $leaf = $this->MaybeGetLeaf($leaf);
79
80 24
        $reference = $referenceId;
81
82 24
        if ( ! ($referenceId instanceof DaftNestedWriteableObject)) {
83
            /**
84
            * @var scalar|(scalar|array|object|null)[]
85
            */
86 24
            $referenceId = $referenceId;
87
88 24
            $reference = $this->RecallDaftObject($referenceId);
89
        }
90
91
        /**
92
        * @var DaftNestedWriteableObject|null
93
        *
94
        * @psalm-var T|null
95
        */
96 24
        $reference = $reference;
97
98 24
        $resp = $this->ModifyDaftNestedObjectTreeInsertMaybeLooseIntoTree(
99 24
            $this,
100 24
            $leaf,
101 24
            $reference,
102 24
            $referenceId === $this->GetNestedObjectTreeRootId(),
103 24
            $before,
104 24
            $above
105
        );
106
107 24
        if ($resp instanceof DaftNestedWriteableObject) {
108 24
            return $resp;
109
        }
110
111
        throw new InvalidArgumentException(sprintf(
112
            'Argument %u passed to %s() did not resolve to a leaf node!',
113
            is_null($leaf) ? self::INT_ARG_INDEX_FIRST : self::INT_ARG_INDEX_SECOND,
114
            __METHOD__
115
        ));
116
    }
117
118
    /**
119
    * @psalm-param T $root
120
    * @psalm-param T|null $replacementRoot
121
    */
122 8
    public function ModifyDaftNestedObjectTreeRemoveWithObject(
123
        DaftNestedWriteableObject $root,
124
        ? DaftNestedWriteableObject $replacementRoot
125
    ) : int {
126
        if (
127 8
            $this->CountDaftNestedObjectTreeWithObject(
128 8
                $root,
129 8
                false,
130 8
                null
131 8
            ) > AbstractArrayBackedDaftNestedObject::COUNT_EXPECT_NON_EMPTY &&
132 8
            is_null($replacementRoot)
133
        ) {
134 2
            throw new BadMethodCallException('Cannot leave orphan objects in a tree');
135
        }
136
137 6
        $root = $this->StoreThenRetrieveFreshLeaf($root);
138
139 6
        if ( ! is_null($replacementRoot)) {
140 4
            $this->ModifyDaftNestedObjectTreeRemoveWithObjectPrepareRemovalAndRebuild(
141 4
                $root,
142 4
                $replacementRoot
143
            );
144
        }
145
146 6
        $this->RemoveDaftObject($root);
147
148 6
        $this->RebuildTreeInefficiently();
149
150 6
        return $this->CountDaftNestedObjectFullTree();
151
    }
152
153
    /**
154
    * @param scalar|(scalar|array|object|null)[] $root
155
    * @param scalar|(scalar|array|object|null)[]|null $replacementRoot
156
    */
157 12
    public function ModifyDaftNestedObjectTreeRemoveWithId($root, $replacementRoot) : int
158
    {
159 12
        $rootObject = $this->RecallDaftObject($root);
160
161 12
        $resp = null;
162
163 12
        if ($rootObject instanceof DaftNestedWriteableObject) {
164 12
            $resp = $this->ModifyDaftNestedObjectTreeRemoveWithIdUsingRootObject(
165 12
                $replacementRoot,
166 12
                $rootObject
167
            );
168
        }
169
170 8
        return is_int($resp) ? $resp : $this->CountDaftNestedObjectFullTree();
171
    }
172
173
    /**
174
    * @psalm-param T $leaf
175
    *
176
    * @psalm-return T
177
    */
178 62
    public function StoreThenRetrieveFreshLeaf(
179
        DaftNestedWriteableObject $leaf
180
    ) : DaftNestedWriteableObject {
181 62
        $this->RememberDaftObject($leaf);
182 62
        $this->ForgetDaftObject($leaf);
183 62
        $this->ForgetDaftObjectById($leaf->GetId());
184
185 62
        $fresh = $this->RecallDaftObject($leaf->GetId());
186
187 62
        if ( ! ($fresh instanceof DaftNestedWriteableObject)) {
188 2
            throw new RuntimeException('Was not able to obtain a fresh copy of the object!');
189
        }
190
191 60
        return $fresh;
192
    }
193
194
    /**
195
    * @psalm-param T $object
196
    */
197 88
    public function RememberDaftObject(SuitableForRepositoryType $object) : void
198
    {
199
        /**
200
        * @var DaftNestedWriteableObject
201
        *
202
        * @psalm-var T
203
        */
204 88
        $object = $object;
205
206 88
        $left = $object->GetIntNestedLeft();
0 ignored issues
show
Bug introduced by
The method GetIntNestedLeft() does not exist on SignpostMarv\DaftObject\SuitableForRepositoryType. It seems like you code against a sub-type of SignpostMarv\DaftObject\SuitableForRepositoryType such as SignpostMarv\DaftObject\DaftNestedObject. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

206
        /** @scrutinizer ignore-call */ 
207
        $left = $object->GetIntNestedLeft();
Loading history...
207 88
        $right = $object->GetIntNestedRight();
0 ignored issues
show
Bug introduced by
The method GetIntNestedRight() does not exist on SignpostMarv\DaftObject\SuitableForRepositoryType. It seems like you code against a sub-type of SignpostMarv\DaftObject\SuitableForRepositoryType such as SignpostMarv\DaftObject\DaftNestedObject. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

207
        /** @scrutinizer ignore-call */ 
208
        $right = $object->GetIntNestedRight();
Loading history...
208 88
        $level = $object->GetIntNestedLevel();
0 ignored issues
show
Bug introduced by
The method GetIntNestedLevel() does not exist on SignpostMarv\DaftObject\SuitableForRepositoryType. It seems like you code against a sub-type of SignpostMarv\DaftObject\SuitableForRepositoryType such as SignpostMarv\DaftObject\DaftNestedObject. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

208
        /** @scrutinizer ignore-call */ 
209
        $level = $object->GetIntNestedLevel();
Loading history...
209
210 88
        if (0 === $left && 0 === $right && 0 === $level) {
211 86
            $fullTreeCount = $this->CountDaftNestedObjectFullTree();
212
213 86
            if ($fullTreeCount > AbstractArrayBackedDaftNestedObject::COUNT_EXPECT_NON_EMPTY) {
214 60
                $tree = $this->RecallDaftNestedObjectFullTree();
215
216
                /**
217
                * @var DaftNestedWriteableObject
218
                *
219
                * @psalm-var T
220
                */
221 60
                $end = end($tree);
222
223 60
                $left = $end->GetIntNestedRight() + 1;
224
            } else {
225 86
                $left = $fullTreeCount + $fullTreeCount;
226
            }
227
228 86
            $object->SetIntNestedLeft($left);
0 ignored issues
show
Bug introduced by
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\...yBackedDaftNestedObject. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

228
            $object->/** @scrutinizer ignore-call */ 
229
                     SetIntNestedLeft($left);
Loading history...
229 86
            $object->SetIntNestedRight($left + 1);
0 ignored issues
show
Bug introduced by
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\...yBackedDaftNestedObject. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

229
            $object->/** @scrutinizer ignore-call */ 
230
                     SetIntNestedRight($left + 1);
Loading history...
230
        }
231
232 88
        parent::RememberDaftObject($object);
233 88
    }
234
235
    /**
236
    * @psalm-param T $newLeaf
237
    * @psalm-param T $referenceLeaf
238
    */
239 52
    protected function ModifyDaftNestedObjectTreeInsertAdjacent(
240
        DaftNestedWriteableObject $newLeaf,
241
        DaftNestedWriteableObject $referenceLeaf,
242
        bool $before
243
    ) : void {
244
        /**
245
        * @var array<int, DaftNestedWriteableObject>
246
        *
247
        * @psalm-var array<int, T>
248
        */
249 52
        $siblings = $this->SiblingsExceptLeaf($newLeaf, $referenceLeaf);
250
251 52
        $siblingIds = [];
252 52
        $siblingSort = [];
253 52
        $j = count($siblings);
254
255 52
        foreach ($siblings as $leaf) {
256
            /**
257
            * @var scalar|(scalar|array|object|null)[]
258
            */
259 28
            $siblingId = $leaf->GetId();
260 28
            $siblingIds[] = $siblingId;
261 28
            $siblingSort[] = $leaf->GetIntNestedSortOrder();
262
        }
263
264 52
        $pos = array_search($referenceLeaf->GetId(), $siblingIds, true);
265
266 52
        if (false === $pos) {
267 24
            throw new RuntimeException('Reference leaf not found in siblings tree!');
268
        }
269
270 28
        for ($i = 0; $i < $j; ++$i) {
271 28
            $siblings[$i]->SetIntNestedSortOrder(
272 28
                $siblingSort[$i] +
273 28
                (($before ? ($i < $pos) : ($i <= $pos)) ? self::DECREMENT : self::INCREMENT)
274
            );
275 28
            $this->StoreThenRetrieveFreshLeaf($siblings[$i]);
276
        }
277
278 28
        $newLeaf->SetIntNestedSortOrder($siblingSort[$pos]);
279 28
        $newLeaf->AlterDaftNestedObjectParentId($referenceLeaf->ObtainDaftNestedObjectParentId());
280
281 28
        $this->StoreThenRetrieveFreshLeaf($newLeaf);
282 28
    }
283
284 60
    protected function RebuildTreeInefficiently() : void
285
    {
286 60
        $rebuilder = new InefficientDaftNestedRebuild($this);
287 60
        $rebuilder->RebuildTree();
288 60
    }
289
290
    /**
291
    * @psalm-param T|null $leaf
292
    * @psalm-param T|null $reference
293
    *
294
    * @psalm-return T|null
295
    */
296 24
    private function ModifyDaftNestedObjectTreeInsertMaybeLooseIntoTree(
297
        DaftNestedWriteableObjectTree $tree,
298
        ? DaftNestedWriteableObject $leaf,
299
        ? DaftObject $reference,
300
        bool $isRoot,
301
        bool $before,
302
        ? bool $above
303
    ) : ? DaftNestedWriteableObject {
304 24
        if ( ! is_null($leaf) && (($reference instanceof DaftNestedWriteableObject) || $isRoot)) {
305 24
            if ($reference instanceof DaftNestedWriteableObject) {
306 18
                return $tree->ModifyDaftNestedObjectTreeInsert($leaf, $reference, $before, $above);
307
            }
308
309 24
            return $this->ModifyDaftNestedObjectTreeInsertLooseIntoTree($leaf, $before, $above);
310
        }
311
312
        return null;
313
    }
314
315
    /**
316
    * @psalm-param T $newLeaf
317
    *
318
    * @psalm-return T
319
    */
320 60
    private function RebuildAfterInsert(
321
        DaftNestedWriteableObject $newLeaf
322
    ) : DaftNestedWriteableObject {
323 60
        $this->RebuildTreeInefficiently();
324
325 60
        $newLeaf = $this->RecallDaftObject($newLeaf->GetId());
326
327 60
        if ( ! ($newLeaf instanceof DaftNestedWriteableObject)) {
328 12
            throw new RuntimeException('Could not retrieve leaf from tree after rebuilding!');
329
        }
330
331 48
        return $newLeaf;
332
    }
333
334
    /**
335
    * @psalm-param T $root
336
    * @psalm-param T $replacementRoot
337
    */
338 4
    private function ModifyDaftNestedObjectTreeRemoveWithObjectPrepareRemovalAndRebuild(
339
        DaftNestedWriteableObject $root,
340
        DaftNestedWriteableObject $replacementRoot
341
    ) : void {
342
        /**
343
        * @var scalar|(scalar|array|object|null)[]
344
        */
345 4
        $replacementRootId = $this->StoreThenRetrieveFreshLeaf($replacementRoot)->GetId();
346
347 4
        $this->UpdateRoots($root, $replacementRootId);
348 4
    }
349
350
    /**
351
    * @param scalar|(scalar|array|object|null)[] $replacementRootId
352
    *
353
    * @psalm-param T $root
354
    */
355 10
    private function UpdateRoots(DaftNestedWriteableObject $root, $replacementRootId) : void
356
    {
357
        /**
358
        * @var array<int, DaftNestedObject>
359
        */
360 10
        $alterThese = $this->RecallDaftNestedObjectTreeWithObject($root, false, self::LIMIT_ONE);
361
362 10
        foreach ($alterThese as $alter) {
363 4
            if ($alter instanceof DaftNestedWriteableObject) {
364 4
                $alter->AlterDaftNestedObjectParentId($replacementRootId);
365 4
                $this->RememberDaftObject($alter);
366
            }
367
        }
368 10
    }
369
370
    /**
371
    * @param DaftNestedWriteableObject|scalar|(scalar|array|object|null)[] $leaf
372
    *
373
    * @psalm-param T|scalar|(scalar|array|object|null)[] $leaf
374
    */
375 48
    private function MaybeGetLeaf($leaf) : ? DaftNestedWriteableObject
376
    {
377 48
        if ($leaf === $this->GetNestedObjectTreeRootId()) {
378 24
            throw new InvalidArgumentException('Cannot pass root id as new leaf');
379 24
        } elseif ($leaf instanceof DaftNestedWriteableObject) {
380 24
            return $this->StoreThenRetrieveFreshLeaf($leaf);
381
        }
382
383
        /**
384
        * @psalm-var scalar|(scalar|array|object|null)[]
385
        */
386 16
        $leaf = $leaf;
387
388
        /**
389
        * @var DaftNestedWriteableObject|null
390
        *
391
        * @psalm-var T|null
392
        */
393 16
        $out = $this->RecallDaftObject($leaf);
394
395 16
        return $out;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $out could return the type SignpostMarv\DaftObject\SuitableForRepositoryType which includes types incompatible with the type-hinted return SignpostMarv\DaftObject\...tedWriteableObject|null. Consider adding an additional type-check to rule them out.
Loading history...
396
    }
397
398
    /**
399
    * @psalm-param T $leaf
400
    *
401
    * @psalm-return T
402
    */
403 24
    private function ModifyDaftNestedObjectTreeInsertLooseIntoTree(
404
        DaftNestedWriteableObject $leaf,
405
        bool $before,
406
        ? bool $above
407
    ) : DaftNestedWriteableObject {
408
        /**
409
        * @var array<int, DaftNestedWriteableObject>
410
        *
411
        * @psalm-var array<int, T>
412
        */
413 24
        $leaves = $this->RecallDaftNestedObjectFullTree(self::RELATIVE_DEPTH_SAME);
414 24
        $leaves = array_filter(
415 24
            $leaves,
416
            /**
417
            * @psalm-param T $e
418
            */
419
            function (DaftNestedWriteableObject $e) use ($leaf) : bool {
420 24
                return $e->GetId() !== $leaf->GetId();
421 24
            }
422
        );
423
424
        /**
425
        * @var false|DaftNestedWriteableObject
426
        *
427
        * @psalm-var false|T
428
        */
429 24
        $reference = $before ? current($leaves) : end($leaves);
430
431 24
        if ( ! ($reference instanceof DaftNestedWriteableObject)) {
432 24
            $leaf->SetIntNestedLeft(0);
433 24
            $leaf->SetIntNestedRight(1);
434 24
            $leaf->SetIntNestedLevel(0);
435 24
            $leaf->AlterDaftNestedObjectParentId($this->GetNestedObjectTreeRootId());
436
437 24
            return $this->StoreThenRetrieveFreshLeaf($leaf);
438
        }
439
440 24
        return $this->ModifyDaftNestedObjectTreeInsert($leaf, $reference, $before, $above);
441
    }
442
443
    /**
444
    * @psalm-param T $rootObject
445
    * @psalm-param T|null $replacementRootObject
446
    */
447 4
    private function MaybeRemoveWithPossibleObject(
448
        DaftNestedWriteableObject $rootObject,
449
        ? DaftObject $replacementRootObject
450
    ) : int {
451 4
        if ( ! ($replacementRootObject instanceof DaftNestedWriteableObject)) {
452 2
            throw new InvalidArgumentException(
453 2
                'Could not locate replacement root, cannot leave orphan objects!'
454
            );
455
        }
456
457 2
        return $this->ModifyDaftNestedObjectTreeRemoveWithObject(
458 2
            $rootObject,
459 2
            $replacementRootObject
460
        );
461
    }
462
463
    /**
464
    * @param scalar|(scalar|array|object|null)[] $replacementRoot
465
    *
466
    * @psalm-param T $rootObject
467
    */
468 6
    private function UpdateRemoveThenRebuild(
469
        DaftNestedWriteableObject $rootObject,
470
        $replacementRoot
471
    ) : void {
472 6
        $this->UpdateRoots($rootObject, $replacementRoot);
473
474 6
        $this->RemoveDaftObject($rootObject);
475
476 6
        $this->RebuildTreeInefficiently();
477 6
    }
478
479
    /**
480
    * @psalm-param T $newLeaf
481
    * @psalm-param T $referenceLeaf
482
    */
483 48
    private function ModifyDaftNestedObjectTreeInsertAbove(
484
        DaftNestedWriteableObject $newLeaf,
485
        DaftNestedWriteableObject $referenceLeaf
486
    ) : void {
487 48
        $newLeaf->AlterDaftNestedObjectParentId($referenceLeaf->ObtainDaftNestedObjectParentId());
488 48
        $referenceLeaf->AlterDaftNestedObjectParentId($newLeaf->GetId());
489
490 48
        $this->StoreThenRetrieveFreshLeaf($newLeaf);
491 48
        $this->StoreThenRetrieveFreshLeaf($referenceLeaf);
492 48
    }
493
494
    /**
495
    * @psalm-param T $newLeaf
496
    * @psalm-param T $referenceLeaf
497
    */
498 6
    private function ModifyDaftNestedObjectTreeInsertBelow(
499
        DaftNestedWriteableObject $newLeaf,
500
        DaftNestedWriteableObject $referenceLeaf
501
    ) : void {
502 6
        $newLeaf->AlterDaftNestedObjectParentId($referenceLeaf->GetId());
503 6
        $this->StoreThenRetrieveFreshLeaf($newLeaf);
504 6
    }
505
506
    /**
507
    * @psalm-param T $newLeaf
508
    * @psalm-param T $referenceLeaf
509
    *
510
    * @psalm-return array<int, T>
511
    */
512 52
    private function SiblingsExceptLeaf(
513
        DaftNestedWriteableObject $newLeaf,
514
        DaftNestedWriteableObject $referenceLeaf
515
    ) : array {
516
        /**
517
        * @var array<int, DaftNestedWriteableObject>
518
        *
519
        * @psalm-var array<int, T>
520
        */
521 52
        $siblings = $this->RecallDaftNestedObjectTreeWithId(
522 52
            $referenceLeaf->ObtainDaftNestedObjectParentId(),
523 52
            self::EXCLUDE_ROOT,
524 52
            self::RELATIVE_DEPTH_SAME
525
        );
526
527 52
        $siblings = array_values(array_filter(
528 52
            $siblings,
529
            /**
530
            * @psalm-param T $leaf
531
            */
532
            function (DaftNestedWriteableObject $leaf) use ($newLeaf) : bool {
533 28
                return $leaf->GetId() !== $newLeaf->GetId();
534 52
            }
535
        ));
536
537 52
        return $siblings;
538
    }
539
540
    /**
541
    * @param scalar|(scalar|array|object|null)[]|null $replacementRoot
542
    *
543
    * @psalm-param T $rootObject
544
    */
545 12
    private function ModifyDaftNestedObjectTreeRemoveWithIdUsingRootObject(
546
        $replacementRoot,
547
        DaftNestedWriteableObject $rootObject
548
    ) : ? int {
549
        if (
550 12
            $this->CountDaftNestedObjectTreeWithObject(
551 12
                $rootObject,
552 12
                false,
553 12
                null
554 12
            ) > AbstractArrayBackedDaftNestedObject::COUNT_EXPECT_NON_EMPTY &&
555 12
            is_null($replacementRoot)
556
        ) {
557 2
            throw new BadMethodCallException('Cannot leave orphan objects in a tree');
558
        } elseif (
559 10
            ! is_null($replacementRoot) &&
560 10
            $replacementRoot !== $this->GetNestedObjectTreeRootId()
561
        ) {
562 4
            $replacementRoot = $this->RecallDaftObject($replacementRoot);
563
564 4
            return $this->MaybeRemoveWithPossibleObject($rootObject, $replacementRoot);
565
        }
566
567
        /**
568
        * @var scalar|(scalar|array|object|null)[]
569
        */
570 6
        $replacementRoot = $replacementRoot;
571
572 6
        $this->UpdateRemoveThenRebuild($rootObject, $replacementRoot);
573
574 6
        return null;
575
    }
576
}
577