Passed
Push — master ( 73f851...850017 )
by SignpostMarv
02:51
created

ModifyDaftNestedObjectTreeInsertLoose()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 28

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
nc 2
nop 4
dl 0
loc 28
ccs 17
cts 17
cp 1
crap 3
rs 9.472
c 0
b 0
f 0
1
<?php
2
/**
3
* Base daft nested 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
trait TraitWriteableTree
16
{
17
    use TraitWriteableTreeUtilities;
18
19 84
    public function ModifyDaftNestedObjectTreeInsert(
20
        DaftNestedWriteableObject $newLeaf,
21
        DaftNestedWriteableObject $referenceLeaf,
22
        bool $before = false,
23
        bool $above = null
24
    ) : DaftNestedWriteableObject {
25 84
        if ($newLeaf->GetId() === $referenceLeaf->GetId()) {
26 24
            throw new InvalidArgumentException('Cannot modify leaf relative to itself!');
27
        }
28
29 60
        if (true === $above) {
30 48
            $this->ModifyDaftNestedObjectTreeInsertAbove($newLeaf, $referenceLeaf);
31 32
        } elseif (false === $above) {
32 6
            $this->ModifyDaftNestedObjectTreeInsertBelow($newLeaf, $referenceLeaf);
33
        } else {
34 28
            $this->ModifyDaftNestedObjectTreeInsertAdjacent($newLeaf, $referenceLeaf, $before);
35
        }
36
37 60
        return $this->RebuildAfterInsert($newLeaf);
38
    }
39
40
    /**
41
    * @param mixed $leaf
42
    * @param mixed $referenceId
43
    */
44 72
    public function ModifyDaftNestedObjectTreeInsertLoose(
45
        $leaf,
46
        $referenceId,
47
        bool $before = false,
48
        bool $above = null
49
    ) : DaftNestedWriteableObject {
50 72
        $leaf = $this->MaybeGetLeaf($leaf);
51
52 48
        $reference = $this->RecallDaftObject($referenceId);
53 48
        $tree = $this->ThrowIfNotTree();
54
55 48
        $resp = $this->ModifyDaftNestedObjectTreeInsertMaybeLooseIntoTree(
56 48
            $tree,
57 48
            $leaf,
58 48
            $reference,
59 48
            $referenceId === $tree->GetNestedObjectTreeRootId(),
60 48
            $before,
61 48
            $above
62
        );
63
64 48
        if ($resp instanceof DaftNestedWriteableObject) {
65 24
            return $resp;
66
        }
67
68 24
        throw new InvalidArgumentException(sprintf(
69 24
            'Argument %u passed to %s() did not resolve to a leaf node!',
70 24
            is_null($leaf) ? 1 : 2,
71 24
            __METHOD__
72
        ));
73
    }
74
75 8
    public function ModifyDaftNestedObjectTreeRemoveWithObject(
76
        DaftNestedWriteableObject $root,
77
        ? DaftNestedWriteableObject $replacementRoot
78
    ) : int {
79
        if (
80 8
            $this->CountDaftNestedObjectTreeWithObject($root, false, null) > 0 &&
81 8
            is_null($replacementRoot)
82
        ) {
83 2
            throw new BadMethodCallException('Cannot leave orphan objects in a tree');
84
        }
85
86 6
        $root = $this->StoreThenRetrieveFreshLeaf($root);
87
88 6
        if ( ! is_null($replacementRoot)) {
89 4
            $this->ModifyDaftNestedObjectTreeRemoveWithObjectPrepareRemovalAndRebuild(
90 4
                $root,
91 4
                $replacementRoot
92
            );
93
        }
94
95 6
        $this->RemoveDaftObject($root);
96
97 6
        $this->RebuildTreeInefficiently();
98
99 6
        return $this->CountDaftNestedObjectFullTree();
100
    }
101
102
    /**
103
    * @param mixed $root
104
    * @param scalar|scalar[]|null $replacementRoot
105
    */
106 12
    public function ModifyDaftNestedObjectTreeRemoveWithId($root, $replacementRoot) : int
107
    {
108 12
        $rootObject = $this->RecallDaftObject($root);
109
110 12
        $resp = null;
111
112 12
        if ($rootObject instanceof DaftNestedWriteableObject) {
113 12
            $resp = $this->ModifyDaftNestedObjectTreeRemoveWithIdUsingRootObject(
114 12
                $replacementRoot,
115 12
                $rootObject
116
            );
117
        }
118
119 8
        return is_int($resp) ? $resp : $this->CountDaftNestedObjectFullTree();
120
    }
121
122 62
    public function StoreThenRetrieveFreshLeaf(
123
        DaftNestedWriteableObject $leaf
124
    ) : DaftNestedWriteableObject {
125 62
        $this->RememberDaftObject($leaf);
126 62
        $this->ForgetDaftObject($leaf);
127 62
        $this->ForgetDaftObjectById($leaf->GetId());
128
129 62
        $fresh = $this->RecallDaftObject($leaf->GetId());
130
131 62
        if ( ! ($fresh instanceof DaftNestedWriteableObject)) {
132 2
            throw new RuntimeException('Was not able to obtain a fresh copy of the object!');
133
        }
134
135 60
        return $fresh;
136
    }
137
138
    /**
139
    * @param scalar|scalar[]|null $replacementRoot
140
    */
141 12
    protected function ModifyDaftNestedObjectTreeRemoveWithIdUsingRootObject(
142
        $replacementRoot,
143
        DaftNestedWriteableObject $rootObject
144
    ) : ? int {
145 12
        $tree = $this->ThrowIfNotTree();
146
147
        if (
148 12
            $tree->CountDaftNestedObjectTreeWithObject($rootObject, false, null) > 0 &&
149 12
            is_null($replacementRoot)
150
        ) {
151 2
            throw new BadMethodCallException('Cannot leave orphan objects in a tree');
152
        } elseif (
153 10
            ! is_null($replacementRoot) &&
154 10
            $replacementRoot !== $tree->GetNestedObjectTreeRootId()
155
        ) {
156 4
            $replacementRoot = $tree->RecallDaftObject($replacementRoot);
157
158 4
            return $this->MaybeRemoveWithPossibleObject($rootObject, $replacementRoot);
159
        }
160
161
        /**
162
        * @var scalar|scalar[] $replacementRoot
163
        */
164 6
        $replacementRoot = $replacementRoot;
165
166 6
        $this->UpdateRemoveThenRebuild($rootObject, $replacementRoot);
167
168 6
        return null;
169
    }
170
}
171