Passed
Push — master ( 7149d2...ef62e5 )
by SignpostMarv
06:57
created

ModifyDaftNestedObjectTreeInsertLooseIntoTree()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 34
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 15
nc 2
nop 3
dl 0
loc 34
ccs 16
cts 16
cp 1
crap 2
rs 9.7666
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
trait WriteableTreeTrait
19
{
20
    /**
21
    * @psalm-param T $newLeaf
22
    * @psalm-param T $referenceLeaf
23
    *
24
    * @psalm-return T
25
    */
26 84
    public function ModifyDaftNestedObjectTreeInsert(
27
        DaftNestedWriteableObject $newLeaf,
28
        DaftNestedWriteableObject $referenceLeaf,
29
        bool $before = self::INSERT_AFTER,
0 ignored issues
show
Bug introduced by
The constant SignpostMarv\DaftObject\...TreeTrait::INSERT_AFTER was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
30
        bool $above = null
31
    ) : DaftNestedWriteableObject {
32 84
        if ($newLeaf->GetId() === $referenceLeaf->GetId()) {
33 40
            throw new InvalidArgumentException('Cannot modify leaf relative to itself!');
34
        }
35
36 60
        if ((bool) $above) {
37 48
            $this->ModifyDaftNestedObjectTreeInsertAbove($newLeaf, $referenceLeaf);
38 32
        } elseif (self::DEFINITELY_BELOW === $above) {
0 ignored issues
show
Bug introduced by
The constant SignpostMarv\DaftObject\...Trait::DEFINITELY_BELOW was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
39 6
            $this->ModifyDaftNestedObjectTreeInsertBelow($newLeaf, $referenceLeaf);
40
        } else {
41 28
            $this->ModifyDaftNestedObjectTreeInsertAdjacent($newLeaf, $referenceLeaf, $before);
42
        }
43
44 60
        return $this->RebuildAfterInsert($newLeaf);
45
    }
46
47
    /**
48
    * @param DaftNestedWriteableObject|scalar|(scalar|array|object|null)[] $leaf
49
    * @param DaftNestedWriteableObject|scalar|(scalar|array|object|null)[] $referenceId
50
    *
51
    * @psalm-param T|scalar|(scalar|array|object|null)[] $leaf
52
    * @psalm-param T|scalar|(scalar|array|object|null)[] $referenceId
53
    *
54
    * @psalm-return T
55
    */
56 48
    public function ModifyDaftNestedObjectTreeInsertLoose(
57
        $leaf,
58
        $referenceId,
59
        bool $before = self::INSERT_AFTER,
0 ignored issues
show
Bug introduced by
The constant SignpostMarv\DaftObject\...TreeTrait::INSERT_AFTER was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
60
        bool $above = null
61
    ) : DaftNestedWriteableObject {
62
        /**
63
        * @var DaftNestedWriteableObject
64
        *
65
        * @psalm-var T
66
        */
67 48
        $leaf = $this->MaybeGetLeafOrThrow($leaf);
68
69 24
        $reference = $this->MaybeRecallLoose($referenceId);
70
71 24
        if ($reference instanceof DaftNestedWriteableObject) {
0 ignored issues
show
introduced by
$reference is always a sub-type of SignpostMarv\DaftObject\DaftNestedWriteableObject.
Loading history...
72 18
            return $this->ModifyDaftNestedObjectTreeInsert($leaf, $reference, $before, $above);
73
        }
74
75 24
        return $this->ModifyDaftNestedObjectTreeInsertLooseIntoTree($leaf, $before, $above);
76
    }
77
78
    /**
79
    * @psalm-param T $root
80
    * @psalm-param T|null $replacementRoot
81
    */
82 8
    public function ModifyDaftNestedObjectTreeRemoveWithObject(
83
        DaftNestedWriteableObject $root,
84
        ? DaftNestedWriteableObject $replacementRoot
85
    ) : int {
86
        if (
87 8
            $this->CountDaftNestedObjectTreeWithObject(
0 ignored issues
show
Bug introduced by
It seems like CountDaftNestedObjectTreeWithObject() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

87
            $this->/** @scrutinizer ignore-call */ 
88
                   CountDaftNestedObjectTreeWithObject(
Loading history...
88 8
                $root,
89 8
                false,
90 8
                null
91 8
            ) > AbstractArrayBackedDaftNestedObject::COUNT_EXPECT_NON_EMPTY &&
92 8
            is_null($replacementRoot)
93
        ) {
94 2
            throw new BadMethodCallException('Cannot leave orphan objects in a tree');
95
        }
96
97 6
        $root = $this->StoreThenRetrieveFreshLeaf($root);
98
99 6
        if ( ! is_null($replacementRoot)) {
100 4
            $this->UpdateRoots(
101 4
                $root,
102 4
                $this->StoreThenRetrieveFreshLeaf($replacementRoot)->GetId()
103
            );
104
        }
105
106 6
        $this->RemoveDaftObject($root);
0 ignored issues
show
Bug introduced by
It seems like RemoveDaftObject() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

106
        $this->/** @scrutinizer ignore-call */ 
107
               RemoveDaftObject($root);
Loading history...
107
108 6
        $this->RebuildTreeInefficiently();
109
110 6
        return $this->CountDaftNestedObjectFullTree();
0 ignored issues
show
Bug introduced by
It seems like CountDaftNestedObjectFullTree() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

110
        return $this->/** @scrutinizer ignore-call */ CountDaftNestedObjectFullTree();
Loading history...
111
    }
112
113
    /**
114
    * @param scalar|(scalar|array|object|null)[] $root
115
    * @param scalar|(scalar|array|object|null)[]|null $replacementRoot
116
    */
117 12
    public function ModifyDaftNestedObjectTreeRemoveWithId($root, $replacementRoot) : int
118
    {
119 12
        $rootObject = $this->RecallDaftObject($root);
0 ignored issues
show
Bug introduced by
It seems like RecallDaftObject() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

119
        /** @scrutinizer ignore-call */ 
120
        $rootObject = $this->RecallDaftObject($root);
Loading history...
120
121 12
        $resp = null;
122
123 12
        if ($rootObject instanceof DaftNestedWriteableObject) {
124 12
            $resp = $this->ModifyDaftNestedObjectTreeRemoveWithIdUsingRootObject(
125 12
                $replacementRoot,
126 12
                $rootObject
127
            );
128
        }
129
130 8
        return is_int($resp) ? $resp : $this->CountDaftNestedObjectFullTree();
131
    }
132
133
    /**
134
    * @psalm-param T $leaf
135
    *
136
    * @psalm-return T
137
    */
138 62
    public function StoreThenRetrieveFreshLeaf(
139
        DaftNestedWriteableObject $leaf
140
    ) : DaftNestedWriteableObject {
141 62
        $this->RememberDaftObject($leaf);
142 62
        $this->ForgetDaftObject($leaf);
0 ignored issues
show
Bug introduced by
It seems like ForgetDaftObject() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

142
        $this->/** @scrutinizer ignore-call */ 
143
               ForgetDaftObject($leaf);
Loading history...
143 62
        $this->ForgetDaftObjectById($leaf->GetId());
0 ignored issues
show
Bug introduced by
It seems like ForgetDaftObjectById() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

143
        $this->/** @scrutinizer ignore-call */ 
144
               ForgetDaftObjectById($leaf->GetId());
Loading history...
144
145
        /**
146
        * @psalm-var class-string<T>
147
        */
148 62
        $type = get_class($leaf);
149
150
        /**
151
        * @var DaftNestedWriteableObject
152
        *
153
        * @psalm-var T
154
        */
155 62
        $out = $this->RecallDaftObjectOrThrow($leaf->GetId(), $type);
0 ignored issues
show
Bug introduced by
It seems like RecallDaftObjectOrThrow() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

155
        /** @scrutinizer ignore-call */ 
156
        $out = $this->RecallDaftObjectOrThrow($leaf->GetId(), $type);
Loading history...
156
157 60
        return $out;
158
    }
159
160
    /**
161
    * @psalm-param T $object
162
    */
163 88
    public function RememberDaftObject(SuitableForRepositoryType $object) : void
164
    {
165
        /**
166
        * @var DaftNestedWriteableObject
167
        *
168
        * @psalm-var T
169
        */
170 88
        $object = $object;
171
172 88
        if (NestedTypeParanoia::NotYetAppendedToTree($object)) {
173 86
            $fullTreeCount = $this->CountDaftNestedObjectFullTree();
174
175 86
            if ($fullTreeCount > AbstractArrayBackedDaftNestedObject::COUNT_EXPECT_NON_EMPTY) {
176 60
                $tree = $this->RecallDaftNestedObjectFullTree();
0 ignored issues
show
Bug introduced by
It seems like RecallDaftNestedObjectFullTree() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

176
                /** @scrutinizer ignore-call */ 
177
                $tree = $this->RecallDaftNestedObjectFullTree();
Loading history...
177
178
                /**
179
                * @var DaftNestedWriteableObject
180
                *
181
                * @psalm-var T
182
                */
183 60
                $end = end($tree);
184
185 60
                $left = $end->GetIntNestedRight() + 1;
186
            } else {
187 86
                $left = $fullTreeCount + $fullTreeCount;
188
            }
189
190 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

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

191
            $object->/** @scrutinizer ignore-call */ 
192
                     SetIntNestedRight($left + 1);
Loading history...
192
        }
193
194 88
        parent::RememberDaftObject($object);
195 88
    }
196
197
    /**
198
    * @psalm-param T $newLeaf
199
    * @psalm-param T $referenceLeaf
200
    */
201 52
    protected function ModifyDaftNestedObjectTreeInsertAdjacent(
202
        DaftNestedWriteableObject $newLeaf,
203
        DaftNestedWriteableObject $referenceLeaf,
204
        bool $before
205
    ) : void {
206 52
        $siblings = $this->SiblingsExceptLeaf($newLeaf, $referenceLeaf);
207
208 52
        $siblingIds = [];
209 52
        $siblingSort = [];
210 52
        $j = count($siblings);
211
212 52
        foreach ($siblings as $leaf) {
213
            /**
214
            * @var scalar|(scalar|array|object|null)[]
215
            */
216 28
            $siblingId = $leaf->GetId();
217 28
            $siblingIds[] = $siblingId;
218 28
            $siblingSort[] = $leaf->GetIntNestedSortOrder();
219
        }
220
221 52
        $pos = array_search($referenceLeaf->GetId(), $siblingIds, true);
222
223 52
        if (false === $pos) {
224 24
            throw new RuntimeException('Reference leaf not found in siblings tree!');
225
        }
226
227 28
        for ($i = 0; $i < $j; ++$i) {
228 28
            $siblings[$i]->SetIntNestedSortOrder(
229 28
                $siblingSort[$i] +
230 28
                (($before ? ($i < $pos) : ($i <= $pos)) ? self::DECREMENT : self::INCREMENT)
0 ignored issues
show
Bug introduced by
The constant SignpostMarv\DaftObject\...bleTreeTrait::DECREMENT was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
Bug introduced by
The constant SignpostMarv\DaftObject\...bleTreeTrait::INCREMENT was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
231
            );
232 28
            $this->StoreThenRetrieveFreshLeaf($siblings[$i]);
233
        }
234
235 28
        $newLeaf->SetIntNestedSortOrder($siblingSort[$pos]);
236 28
        $newLeaf->AlterDaftNestedObjectParentId($referenceLeaf->ObtainDaftNestedObjectParentId());
237
238 28
        $this->StoreThenRetrieveFreshLeaf($newLeaf);
239 28
    }
240
241 60
    protected function RebuildTreeInefficiently() : void
242
    {
243 60
        $rebuilder = new InefficientDaftNestedRebuild($this);
0 ignored issues
show
Bug introduced by
$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 ignore-type  annotation

243
        $rebuilder = new InefficientDaftNestedRebuild(/** @scrutinizer ignore-type */ $this);
Loading history...
244 60
        $rebuilder->RebuildTree();
245 60
    }
246
247
    /**
248
    * @psalm-param T $newLeaf
249
    *
250
    * @psalm-return T
251
    */
252 60
    private function RebuildAfterInsert(
253
        DaftNestedWriteableObject $newLeaf
254
    ) : DaftNestedWriteableObject {
255 60
        $this->RebuildTreeInefficiently();
256
257
        /**
258
        * @psalm-var class-string<T>
259
        */
260 60
        $type = get_class($newLeaf);
261
262
        /**
263
        * @var DaftNestedWriteableObject
264
        *
265
        * @psalm-var T
266
        */
267 60
        $out = $this->RecallDaftObjectOrThrow($newLeaf->GetId(), $type);
268
269 48
        return $out;
270
    }
271
272
    /**
273
    * @param scalar|(scalar|array|object|null)[] $replacementRootId
274
    *
275
    * @psalm-param T $root
276
    */
277 10
    private function UpdateRoots(DaftNestedWriteableObject $root, $replacementRootId) : void
278
    {
279
        /**
280
        * @var array<int, DaftNestedWriteableObject>
281
        *
282
        * @psalm-var array<int, T>
283
        */
284 10
        $alterThese = $this->RecallDaftNestedObjectTreeWithObject($root, false, self::LIMIT_ONE);
0 ignored issues
show
Bug introduced by
The constant SignpostMarv\DaftObject\...bleTreeTrait::LIMIT_ONE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
Bug introduced by
It seems like RecallDaftNestedObjectTreeWithObject() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

284
        /** @scrutinizer ignore-call */ 
285
        $alterThese = $this->RecallDaftNestedObjectTreeWithObject($root, false, self::LIMIT_ONE);
Loading history...
285
286 10
        foreach ($alterThese as $alter) {
287 4
            $alter->AlterDaftNestedObjectParentId($replacementRootId);
288 4
            $this->RememberDaftObject($alter);
289
        }
290 10
    }
291
292
    /**
293
    * @param DaftNestedWriteableObject|scalar|(scalar|array|object|null)[] $leaf
294
    *
295
    * @psalm-param T|scalar|(scalar|array|object|null)[] $leaf
296
    * @psalm-param class-string<T> $type
297
    *
298
    * @psalm-return T
299
    */
300 48
    private function MaybeGetLeafOrThrow(
301
        $leaf,
302
        string $type = DaftNestedWriteableObject::class
303
    ) : DaftNestedWriteableObject {
304 48
        if ($leaf === $this->GetNestedObjectTreeRootId()) {
0 ignored issues
show
Bug introduced by
It seems like GetNestedObjectTreeRootId() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

304
        if ($leaf === $this->/** @scrutinizer ignore-call */ GetNestedObjectTreeRootId()) {
Loading history...
305 24
            throw new InvalidArgumentException('Cannot pass root id as new leaf');
306 24
        } elseif ($leaf instanceof DaftNestedWriteableObject) {
307 24
            return $this->StoreThenRetrieveFreshLeaf($leaf);
308
        }
309
310
        /**
311
        * @psalm-var scalar|(scalar|array|object|null)[]
312
        */
313 16
        $leaf = $leaf;
314
315
        /**
316
        * @var DaftNestedWriteableObject
317
        *
318
        * @psalm-var T
319
        */
320 16
        $out = $this->RecallDaftObjectOrThrow($leaf, $type);
321
322 16
        return $out;
323
    }
324
325
    /**
326
    * @param DaftNestedWriteableObject|scalar|(scalar|array|object|null)[] $leaf
327
    *
328
    * @psalm-param T|scalar|(scalar|array|object|null)[] $leaf
329
    */
330 24
    private function MaybeRecallLoose($leaf) : ? DaftNestedWriteableObject
331
    {
332 24
        if ($leaf instanceof DaftNestedWriteableObject) {
333 2
            return $leaf;
334
        }
335
336
        /**
337
        * @var scalar|(scalar|array|object|null)[]
338
        */
339 24
        $leaf = $leaf;
340
341
        /**
342
        * @var DaftNestedWriteableObject|null
343
        *
344
        * @psalm-var T|null
345
        */
346 24
        $out = $this->RecallDaftObject($leaf);
347
348 24
        return $out;
349
    }
350
351
    /**
352
    * @psalm-param T $leaf
353
    *
354
    * @psalm-return T
355
    */
356 24
    private function ModifyDaftNestedObjectTreeInsertLooseIntoTree(
357
        DaftNestedWriteableObject $leaf,
358
        bool $before,
359
        ? bool $above
360
    ) : DaftNestedWriteableObject {
361
        /**
362
        * @var array<int, DaftNestedWriteableObject>
363
        *
364
        * @psalm-var array<int, T>
365
        */
366 24
        $leaves = array_filter(
367 24
            $this->RecallDaftNestedObjectFullTree(self::RELATIVE_DEPTH_SAME),
0 ignored issues
show
Bug introduced by
The constant SignpostMarv\DaftObject\...it::RELATIVE_DEPTH_SAME was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
368
            /**
369
            * @psalm-param T $e
370
            */
371
            function (DaftNestedWriteableObject $e) use ($leaf) : bool {
372 24
                return $e->GetId() !== $leaf->GetId();
373 24
            }
374
        );
375
376 24
        if (count($leaves) < 1) {
377 24
            $leaf->SetIntNestedLeft(0);
378 24
            $leaf->SetIntNestedRight(1);
379 24
            $leaf->SetIntNestedLevel(0);
380 24
            $leaf->AlterDaftNestedObjectParentId($this->GetNestedObjectTreeRootId());
381
382 24
            return $this->StoreThenRetrieveFreshLeaf($leaf);
383
        }
384
385 24
        return $this->ModifyDaftNestedObjectTreeInsert(
386 24
            $leaf,
387 24
            NestedTypeParanoia::ObtainFirstOrLast($before, ...$leaves),
388 24
            $before,
389 24
            $above
390
        );
391
    }
392
393
    /**
394
    * @psalm-param T $newLeaf
395
    * @psalm-param T $referenceLeaf
396
    */
397 48
    private function ModifyDaftNestedObjectTreeInsertAbove(
398
        DaftNestedWriteableObject $newLeaf,
399
        DaftNestedWriteableObject $referenceLeaf
400
    ) : void {
401 48
        $newLeaf->AlterDaftNestedObjectParentId($referenceLeaf->ObtainDaftNestedObjectParentId());
402 48
        $referenceLeaf->AlterDaftNestedObjectParentId($newLeaf->GetId());
403
404 48
        $this->StoreThenRetrieveFreshLeaf($newLeaf);
405 48
        $this->StoreThenRetrieveFreshLeaf($referenceLeaf);
406 48
    }
407
408
    /**
409
    * @psalm-param T $newLeaf
410
    * @psalm-param T $referenceLeaf
411
    */
412 6
    private function ModifyDaftNestedObjectTreeInsertBelow(
413
        DaftNestedWriteableObject $newLeaf,
414
        DaftNestedWriteableObject $referenceLeaf
415
    ) : void {
416 6
        $newLeaf->AlterDaftNestedObjectParentId($referenceLeaf->GetId());
417 6
        $this->StoreThenRetrieveFreshLeaf($newLeaf);
418 6
    }
419
420
    /**
421
    * @psalm-param T $newLeaf
422
    * @psalm-param T $referenceLeaf
423
    *
424
    * @return array<int, DaftNestedWriteableObject>
425
    *
426
    * @psalm-return array<int, T>
427
    */
428 52
    private function SiblingsExceptLeaf(
429
        DaftNestedWriteableObject $newLeaf,
430
        DaftNestedWriteableObject $referenceLeaf
431
    ) : array {
432
        /**
433
        * @var array<int, DaftNestedWriteableObject>
434
        *
435
        * @psalm-var array<int, T>
436
        */
437 52
        $out = array_values(array_filter(
438 52
            $this->RecallDaftNestedObjectTreeWithId(
0 ignored issues
show
Bug introduced by
It seems like RecallDaftNestedObjectTreeWithId() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

438
            $this->/** @scrutinizer ignore-call */ 
439
                   RecallDaftNestedObjectTreeWithId(
Loading history...
439 52
                $referenceLeaf->ObtainDaftNestedObjectParentId(),
440 52
                self::EXCLUDE_ROOT,
0 ignored issues
show
Bug introduced by
The constant SignpostMarv\DaftObject\...TreeTrait::EXCLUDE_ROOT was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
441 52
                self::RELATIVE_DEPTH_SAME
0 ignored issues
show
Bug introduced by
The constant SignpostMarv\DaftObject\...it::RELATIVE_DEPTH_SAME was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
442
            ),
443
            /**
444
            * @psalm-param T $leaf
445
            */
446
            function (DaftNestedWriteableObject $leaf) use ($newLeaf) : bool {
447 28
                return $leaf->GetId() !== $newLeaf->GetId();
448 52
            }
449
        ));
450
451 52
        return $out;
452
    }
453
454
    /**
455
    * @param scalar|(scalar|array|object|null)[]|null $replacementRoot
456
    *
457
    * @psalm-param T $rootObject
458
    */
459 12
    private function ModifyDaftNestedObjectTreeRemoveWithIdUsingRootObject(
460
        $replacementRoot,
461
        DaftNestedWriteableObject $rootObject
462
    ) : ? int {
463
        if (
464 12
            $this->CountDaftNestedObjectTreeWithObject(
465 12
                $rootObject,
466 12
                false,
467 12
                null
468 12
            ) > AbstractArrayBackedDaftNestedObject::COUNT_EXPECT_NON_EMPTY &&
469 12
            is_null($replacementRoot)
470
        ) {
471 2
            throw new BadMethodCallException('Cannot leave orphan objects in a tree');
472
        } elseif (
473 10
            ! is_null($replacementRoot) &&
474 10
            $replacementRoot !== $this->GetNestedObjectTreeRootId()
475
        ) {
476
            /**
477
            * @psalm-var class-string<T>
478
            */
479 4
            $type = get_class($rootObject);
480
481
            /**
482
            * @var DaftNestedWriteableObject
483
            *
484
            * @psalm-var T
485
            */
486 4
            $replacement = $this->RecallDaftObjectOrThrow($replacementRoot, $type);
487
488 2
            return $this->ModifyDaftNestedObjectTreeRemoveWithObject(
489 2
                $rootObject,
490 2
                $replacement
491
            );
492
        }
493
494
        /**
495
        * @var scalar|(scalar|array|object|null)[]
496
        */
497 6
        $replacementRoot = $replacementRoot;
498
499 6
        $this->UpdateRoots($rootObject, $replacementRoot);
500
501 6
        $this->RemoveDaftObject($rootObject);
502
503 6
        $this->RebuildTreeInefficiently();
504
505 6
        return null;
506
    }
507
}
508