Passed
Push — master ( b7f313...3401c7 )
by SignpostMarv
06:04
created

RecallDaftNestedWriteableObjectOrThrow()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 22
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2.3149

Importance

Changes 0
Metric Value
cc 2
eloc 11
nc 2
nop 1
dl 0
loc 22
ccs 4
cts 7
cp 0.5714
crap 2.3149
rs 9.9
c 0
b 0
f 0

1 Method

Rating   Name   Duplication   Size   Complexity  
A DaftWriteableObjectMemoryTree::ModifyDaftNestedObjectTreeInsert() 0 19 4
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
        /**
79
        * @var DaftNestedWriteableObject
80
        *
81
        * @psalm-var T
82
        */
83 48
        $leaf = $this->MaybeGetLeafOrThrow($leaf);
84
85 24
        $reference = $this->MaybeRecallLoose($referenceId);
86
87 24
        return $this->ModifyDaftNestedObjectTreeInsertMaybeLooseIntoTree(
88 24
            $this,
89 24
            $leaf,
90 24
            $reference,
91 24
            $referenceId === $this->GetNestedObjectTreeRootId(),
92 24
            $before,
93 24
            $above
94
        );
95
    }
96
97
    /**
98
    * @psalm-param T $root
99
    * @psalm-param T|null $replacementRoot
100
    */
101 8
    public function ModifyDaftNestedObjectTreeRemoveWithObject(
102
        DaftNestedWriteableObject $root,
103
        ? DaftNestedWriteableObject $replacementRoot
104
    ) : int {
105
        if (
106 8
            $this->CountDaftNestedObjectTreeWithObject(
107 8
                $root,
108 8
                false,
109 8
                null
110 8
            ) > AbstractArrayBackedDaftNestedObject::COUNT_EXPECT_NON_EMPTY &&
111 8
            is_null($replacementRoot)
112
        ) {
113 2
            throw new BadMethodCallException('Cannot leave orphan objects in a tree');
114
        }
115
116 6
        $root = $this->StoreThenRetrieveFreshLeaf($root);
117
118 6
        if ( ! is_null($replacementRoot)) {
119 4
            $this->ModifyDaftNestedObjectTreeRemoveWithObjectPrepareRemovalAndRebuild(
120 4
                $root,
121 4
                $replacementRoot
122
            );
123
        }
124
125 6
        $this->RemoveDaftObject($root);
126
127 6
        $this->RebuildTreeInefficiently();
128
129 6
        return $this->CountDaftNestedObjectFullTree();
130
    }
131
132
    /**
133
    * @param scalar|(scalar|array|object|null)[] $root
134
    * @param scalar|(scalar|array|object|null)[]|null $replacementRoot
135
    */
136 12
    public function ModifyDaftNestedObjectTreeRemoveWithId($root, $replacementRoot) : int
137
    {
138 12
        $rootObject = $this->RecallDaftObject($root);
139
140 12
        $resp = null;
141
142 12
        if ($rootObject instanceof DaftNestedWriteableObject) {
143 12
            $resp = $this->ModifyDaftNestedObjectTreeRemoveWithIdUsingRootObject(
144 12
                $replacementRoot,
145 12
                $rootObject
146
            );
147
        }
148
149 8
        return is_int($resp) ? $resp : $this->CountDaftNestedObjectFullTree();
150
    }
151
152
    /**
153
    * @psalm-param T $leaf
154
    *
155
    * @psalm-return T
156
    */
157 62
    public function StoreThenRetrieveFreshLeaf(
158
        DaftNestedWriteableObject $leaf
159
    ) : DaftNestedWriteableObject {
160 62
        $this->RememberDaftObject($leaf);
161 62
        $this->ForgetDaftObject($leaf);
162 62
        $this->ForgetDaftObjectById($leaf->GetId());
163
164
        /**
165
        * @psalm-var class-string<T>
166
        */
167 62
        $type = get_class($leaf);
168
169
        /**
170
        * @var DaftNestedWriteableObject
171
        *
172
        * @psalm-var T
173
        */
174 62
        $out = $this->RecallDaftObjectOrThrow($leaf->GetId(), $type);
175
176 60
        return $out;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $out returns the type SignpostMarv\DaftObject\SuitableForRepositoryType which includes types incompatible with the type-hinted return SignpostMarv\DaftObject\DaftNestedWriteableObject.
Loading history...
177
    }
178
179
    /**
180
    * @psalm-param T $object
181
    */
182 88
    public function RememberDaftObject(SuitableForRepositoryType $object) : void
183
    {
184
        /**
185
        * @var DaftNestedWriteableObject
186
        *
187
        * @psalm-var T
188
        */
189 88
        $object = $object;
190
191 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

191
        /** @scrutinizer ignore-call */ 
192
        $left = $object->GetIntNestedLeft();
Loading history...
192 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

192
        /** @scrutinizer ignore-call */ 
193
        $right = $object->GetIntNestedRight();
Loading history...
193 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

193
        /** @scrutinizer ignore-call */ 
194
        $level = $object->GetIntNestedLevel();
Loading history...
194
195 88
        if (0 === $left && 0 === $right && 0 === $level) {
196 86
            $fullTreeCount = $this->CountDaftNestedObjectFullTree();
197
198 86
            if ($fullTreeCount > AbstractArrayBackedDaftNestedObject::COUNT_EXPECT_NON_EMPTY) {
199 60
                $tree = $this->RecallDaftNestedObjectFullTree();
200
201
                /**
202
                * @var DaftNestedWriteableObject
203
                *
204
                * @psalm-var T
205
                */
206 60
                $end = end($tree);
207
208 60
                $left = $end->GetIntNestedRight() + 1;
209
            } else {
210 86
                $left = $fullTreeCount + $fullTreeCount;
211
            }
212
213 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

213
            $object->/** @scrutinizer ignore-call */ 
214
                     SetIntNestedLeft($left);
Loading history...
214 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

214
            $object->/** @scrutinizer ignore-call */ 
215
                     SetIntNestedRight($left + 1);
Loading history...
215
        }
216
217 88
        parent::RememberDaftObject($object);
218 88
    }
219
220
    /**
221
    * @psalm-param T $newLeaf
222
    * @psalm-param T $referenceLeaf
223
    */
224 52
    protected function ModifyDaftNestedObjectTreeInsertAdjacent(
225
        DaftNestedWriteableObject $newLeaf,
226
        DaftNestedWriteableObject $referenceLeaf,
227
        bool $before
228
    ) : void {
229 52
        $siblings = $this->SiblingsExceptLeaf($newLeaf, $referenceLeaf);
230
231 52
        $siblingIds = [];
232 52
        $siblingSort = [];
233 52
        $j = count($siblings);
234
235 52
        foreach ($siblings as $leaf) {
236
            /**
237
            * @var scalar|(scalar|array|object|null)[]
238
            */
239 28
            $siblingId = $leaf->GetId();
240 28
            $siblingIds[] = $siblingId;
241 28
            $siblingSort[] = $leaf->GetIntNestedSortOrder();
242
        }
243
244 52
        $pos = array_search($referenceLeaf->GetId(), $siblingIds, true);
245
246 52
        if (false === $pos) {
247 24
            throw new RuntimeException('Reference leaf not found in siblings tree!');
248
        }
249
250 28
        for ($i = 0; $i < $j; ++$i) {
251 28
            $siblings[$i]->SetIntNestedSortOrder(
252 28
                $siblingSort[$i] +
253 28
                (($before ? ($i < $pos) : ($i <= $pos)) ? self::DECREMENT : self::INCREMENT)
254
            );
255 28
            $this->StoreThenRetrieveFreshLeaf($siblings[$i]);
256
        }
257
258 28
        $newLeaf->SetIntNestedSortOrder($siblingSort[$pos]);
259 28
        $newLeaf->AlterDaftNestedObjectParentId($referenceLeaf->ObtainDaftNestedObjectParentId());
260
261 28
        $this->StoreThenRetrieveFreshLeaf($newLeaf);
262 28
    }
263
264 60
    protected function RebuildTreeInefficiently() : void
265
    {
266 60
        $rebuilder = new InefficientDaftNestedRebuild($this);
267 60
        $rebuilder->RebuildTree();
268 60
    }
269
270 24
    private function ModifyDaftNestedObjectTreeInsertMaybeLooseIntoTree(
271
        DaftNestedWriteableObjectTree $tree,
272
        DaftNestedWriteableObject $leaf,
273
        ? DaftNestedWriteableObject $reference,
274
        bool $isRoot,
0 ignored issues
show
Unused Code introduced by
The parameter $isRoot is not used and could be removed. ( Ignorable by Annotation )

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

274
        /** @scrutinizer ignore-unused */ bool $isRoot,

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
275
        bool $before,
276
        ? bool $above
277
    ) : DaftNestedWriteableObject {
278 24
        if ($reference instanceof DaftNestedWriteableObject) {
279 18
            return $tree->ModifyDaftNestedObjectTreeInsert($leaf, $reference, $before, $above);
280
        }
281
282 24
        return $this->ModifyDaftNestedObjectTreeInsertLooseIntoTree($leaf, $before, $above);
283
    }
284
285
    /**
286
    * @psalm-param T $newLeaf
287
    *
288
    * @psalm-return T
289
    */
290 60
    private function RebuildAfterInsert(
291
        DaftNestedWriteableObject $newLeaf
292
    ) : DaftNestedWriteableObject {
293 60
        $this->RebuildTreeInefficiently();
294
295
        /**
296
        * @psalm-var class-string<T>
297
        */
298 60
        $type = get_class($newLeaf);
299
300
        /**
301
        * @var DaftNestedWriteableObject
302
        *
303
        * @psalm-var T
304
        */
305 60
        $out = $this->RecallDaftObjectOrThrow($newLeaf->GetId(), $type);
306
307 48
        return $out;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $out returns the type SignpostMarv\DaftObject\SuitableForRepositoryType which includes types incompatible with the type-hinted return SignpostMarv\DaftObject\DaftNestedWriteableObject.
Loading history...
308
    }
309
310
    /**
311
    * @psalm-param T $root
312
    * @psalm-param T $replacementRoot
313
    */
314 4
    private function ModifyDaftNestedObjectTreeRemoveWithObjectPrepareRemovalAndRebuild(
315
        DaftNestedWriteableObject $root,
316
        DaftNestedWriteableObject $replacementRoot
317
    ) : void {
318 4
        $this->UpdateRoots($root, $this->StoreThenRetrieveFreshLeaf($replacementRoot)->GetId());
319 4
    }
320
321
    /**
322
    * @param scalar|(scalar|array|object|null)[] $replacementRootId
323
    *
324
    * @psalm-param T $root
325
    */
326 10
    private function UpdateRoots(DaftNestedWriteableObject $root, $replacementRootId) : void
327
    {
328
        /**
329
        * @var array<int, DaftNestedWriteableObject>
330
        *
331
        * @psalm-var array<int, T>
332
        */
333 10
        $alterThese = $this->RecallDaftNestedObjectTreeWithObject($root, false, self::LIMIT_ONE);
334
335 10
        foreach ($alterThese as $alter) {
336 4
            $alter->AlterDaftNestedObjectParentId($replacementRootId);
337 4
            $this->RememberDaftObject($alter);
338
        }
339 10
    }
340
341
    /**
342
    * @param DaftNestedWriteableObject|scalar|(scalar|array|object|null)[] $leaf
343
    *
344
    * @psalm-param T|scalar|(scalar|array|object|null)[] $leaf
345
    * @psalm-param class-string<T> $type
346
    *
347
    * @psalm-return T
348
    */
349 48
    private function MaybeGetLeafOrThrow(
350
        $leaf,
351
        string $type = DaftNestedWriteableObject::class
352
    ) : DaftNestedWriteableObject {
353 48
        if ($leaf === $this->GetNestedObjectTreeRootId()) {
354 24
            throw new InvalidArgumentException('Cannot pass root id as new leaf');
355 24
        } elseif ($leaf instanceof DaftNestedWriteableObject) {
356 24
            return $this->StoreThenRetrieveFreshLeaf($leaf);
357
        }
358
359
        /**
360
        * @psalm-var scalar|(scalar|array|object|null)[]
361
        */
362 16
        $leaf = $leaf;
363
364
        /**
365
        * @var DaftNestedWriteableObject
366
        *
367
        * @psalm-var T
368
        */
369 16
        $out = $this->RecallDaftObjectOrThrow($leaf, $type);
370
371 16
        return $out;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $out returns the type SignpostMarv\DaftObject\SuitableForRepositoryType which includes types incompatible with the type-hinted return SignpostMarv\DaftObject\DaftNestedWriteableObject.
Loading history...
372
    }
373
374
    /**
375
    * @param DaftNestedWriteableObject|scalar|(scalar|array|object|null)[] $leaf
376
    *
377
    * @psalm-param T|scalar|(scalar|array|object|null)[] $leaf
378
    */
379 24
    private function MaybeRecallLoose($leaf) : ? DaftNestedWriteableObject
380
    {
381 24
        if ($leaf instanceof DaftNestedWriteableObject) {
382 2
            return $leaf;
383
        }
384
385
        /**
386
        * @var scalar|(scalar|array|object|null)[]
387
        */
388 24
        $leaf = $leaf;
389
390
        /**
391
        * @var DaftNestedWriteableObject|null
392
        *
393
        * @psalm-var T|null
394
        */
395 24
        $out = $this->RecallDaftObject($leaf);
396
397 24
        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...
398
    }
399
400
    /**
401
    * @psalm-param T $leaf
402
    *
403
    * @psalm-return T
404
    */
405 24
    private function ModifyDaftNestedObjectTreeInsertLooseIntoTree(
406
        DaftNestedWriteableObject $leaf,
407
        bool $before,
408
        ? bool $above
409
    ) : DaftNestedWriteableObject {
410
        /**
411
        * @var array<int, DaftNestedWriteableObject>
412
        *
413
        * @psalm-var array<int, T>
414
        */
415 24
        $leaves = array_filter(
416 24
            $this->RecallDaftNestedObjectFullTree(self::RELATIVE_DEPTH_SAME),
417
            /**
418
            * @psalm-param T $e
419
            */
420
            function (DaftNestedWriteableObject $e) use ($leaf) : bool {
421 24
                return $e->GetId() !== $leaf->GetId();
422 24
            }
423
        );
424
425 24
        if (count($leaves) < 1) {
426 24
            $leaf->SetIntNestedLeft(0);
427 24
            $leaf->SetIntNestedRight(1);
428 24
            $leaf->SetIntNestedLevel(0);
429 24
            $leaf->AlterDaftNestedObjectParentId($this->GetNestedObjectTreeRootId());
430
431 24
            return $this->StoreThenRetrieveFreshLeaf($leaf);
432
        }
433
434
        /**
435
        * @psalm-var T
436
        */
437 24
        $reference = $before ? current($leaves) : end($leaves);
438
439 24
        return $this->ModifyDaftNestedObjectTreeInsert($leaf, $reference, $before, $above);
440
    }
441
442
    /**
443
    * @psalm-param T $newLeaf
444
    * @psalm-param T $referenceLeaf
445
    */
446 48
    private function ModifyDaftNestedObjectTreeInsertAbove(
447
        DaftNestedWriteableObject $newLeaf,
448
        DaftNestedWriteableObject $referenceLeaf
449
    ) : void {
450 48
        $newLeaf->AlterDaftNestedObjectParentId($referenceLeaf->ObtainDaftNestedObjectParentId());
451 48
        $referenceLeaf->AlterDaftNestedObjectParentId($newLeaf->GetId());
452
453 48
        $this->StoreThenRetrieveFreshLeaf($newLeaf);
454 48
        $this->StoreThenRetrieveFreshLeaf($referenceLeaf);
455 48
    }
456
457
    /**
458
    * @psalm-param T $newLeaf
459
    * @psalm-param T $referenceLeaf
460
    */
461 6
    private function ModifyDaftNestedObjectTreeInsertBelow(
462
        DaftNestedWriteableObject $newLeaf,
463
        DaftNestedWriteableObject $referenceLeaf
464
    ) : void {
465 6
        $newLeaf->AlterDaftNestedObjectParentId($referenceLeaf->GetId());
466 6
        $this->StoreThenRetrieveFreshLeaf($newLeaf);
467 6
    }
468
469
    /**
470
    * @psalm-param T $newLeaf
471
    * @psalm-param T $referenceLeaf
472
    *
473
    * @return array<int, DaftNestedWriteableObject>
474
    *
475
    * @psalm-return array<int, T>
476
    */
477 52
    private function SiblingsExceptLeaf(
478
        DaftNestedWriteableObject $newLeaf,
479
        DaftNestedWriteableObject $referenceLeaf
480
    ) : array {
481
        /**
482
        * @var array<int, DaftNestedWriteableObject>
483
        *
484
        * @psalm-var array<int, T>
485
        */
486 52
        $out = array_values(array_filter(
487 52
            $this->RecallDaftNestedObjectTreeWithId(
488 52
                $referenceLeaf->ObtainDaftNestedObjectParentId(),
489 52
                self::EXCLUDE_ROOT,
490 52
                self::RELATIVE_DEPTH_SAME
491
            ),
492
            /**
493
            * @psalm-param T $leaf
494
            */
495
            function (DaftNestedWriteableObject $leaf) use ($newLeaf) : bool {
496 28
                return $leaf->GetId() !== $newLeaf->GetId();
497 52
            }
498
        ));
499
500 52
        return $out;
501
    }
502
503
    /**
504
    * @param scalar|(scalar|array|object|null)[]|null $replacementRoot
505
    *
506
    * @psalm-param T $rootObject
507
    */
508 12
    private function ModifyDaftNestedObjectTreeRemoveWithIdUsingRootObject(
509
        $replacementRoot,
510
        DaftNestedWriteableObject $rootObject
511
    ) : ? int {
512
        if (
513 12
            $this->CountDaftNestedObjectTreeWithObject(
514 12
                $rootObject,
515 12
                false,
516 12
                null
517 12
            ) > AbstractArrayBackedDaftNestedObject::COUNT_EXPECT_NON_EMPTY &&
518 12
            is_null($replacementRoot)
519
        ) {
520 2
            throw new BadMethodCallException('Cannot leave orphan objects in a tree');
521
        } elseif (
522 10
            ! is_null($replacementRoot) &&
523 10
            $replacementRoot !== $this->GetNestedObjectTreeRootId()
524
        ) {
525
            /**
526
            * @psalm-var class-string<T>
527
            */
528 4
            $type = get_class($rootObject);
529
530
            /**
531
            * @var DaftNestedWriteableObject
532
            *
533
            * @psalm-var T
534
            */
535 4
            $replacement = $this->RecallDaftObjectOrThrow($replacementRoot, $type);
536
537 2
            return $this->ModifyDaftNestedObjectTreeRemoveWithObject(
538 2
                $rootObject,
539 2
                $replacement
540
            );
541
        }
542
543
        /**
544
        * @var scalar|(scalar|array|object|null)[]
545
        */
546 6
        $replacementRoot = $replacementRoot;
547
548 6
        $this->UpdateRoots($rootObject, $replacementRoot);
549
550 6
        $this->RemoveDaftObject($rootObject);
551
552 6
        $this->RebuildTreeInefficiently();
553
554 6
        return null;
555
    }
556
}
557