Passed
Push — master ( e30a03...64a568 )
by SignpostMarv
02:42
created

AbstractDaftObjectEasyDBTree   A

Complexity

Total Complexity 35

Size/Duplication

Total Lines 280
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
dl 0
loc 280
ccs 137
cts 137
cp 1
rs 9
c 0
b 0
f 0
wmc 35

18 Methods

Rating   Name   Duplication   Size   Complexity  
A RecallDaftNestedObjectTreeWithObject() 0 10 2
A RecallDaftNestedObjectFullTree() 0 3 1
A CompareObjects() 0 3 1
A RecallDaftNestedObjectPathToObject() 0 10 1
A CountDaftNestedObjectPathToId() 0 8 2
A CountDaftNestedObjectTreeWithObject() 0 10 2
A CountDaftNestedObjectPathToObject() 0 10 1
A RecallDaftNestedObjectPathToId() 0 8 2
A CountDaftNestedObjectFullTree() 0 3 1
A CountDaftNestedObjectTreeWithId() 0 18 3
A RecallDaftNestedObjectTreeWithId() 0 18 3
A SelectingQueryDaftNestedObjectTreeFromArgs() 0 17 2
A FilterQueryDaftNestedObjectTreeFromArgs() 0 3 2
A RememberDaftObjectData() 0 5 1
B DaftObjectRepositoryByType() 0 25 4
B QueryDaftNestedObjectTreeFromArgs() 0 47 5
A RecallDaftNestedObjectTreeFromArgs() 0 20 1
A CountDaftNestedObjectTreeFromArgs() 0 17 1
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 ParagonIE\EasyDB\EasyDB;
12
use PDO;
13
use PDOStatement;
14
15
abstract class AbstractDaftObjectEasyDBTree extends AbstractDaftObjectEasyDBRepository implements DaftNestedObjectTree
16
{
17 28
    public function RecallDaftNestedObjectFullTree(int $limit = null) : array
18
    {
19 28
        return $this->RecallDaftNestedObjectTreeFromArgs(null, null, $limit, false);
20
    }
21
22 14
    public function CountDaftNestedObjectFullTree(int $withLimit = null) : int
23
    {
24 14
        return $this->CountDaftNestedObjectTreeFromArgs(null, null, $withLimit, false);
25
    }
26
27 14
    public function RecallDaftNestedObjectTreeWithObject(
28
        DaftNestedObject $root,
29
        bool $withRoot,
30
        ? int $limit
31
    ) : array {
32 14
        $left = $root->GetIntNestedLeft();
33 14
        $right = $root->GetIntNestedRight();
34 14
        $limit = is_int($limit) ? ($root->GetIntNestedLevel() + $limit) : null;
35
36 14
        return $this->RecallDaftNestedObjectTreeFromArgs($left, $right, $limit, $withRoot);
37
    }
38
39 20
    public function CountDaftNestedObjectTreeWithObject(
40
        DaftNestedObject $root,
41
        bool $withRoot,
42
        ? int $limit
43
    ) : int {
44 20
        $left = $root->GetIntNestedLeft();
45 20
        $right = $root->GetIntNestedRight();
46 20
        $limit = is_int($limit) ? ($root->GetIntNestedLevel() + $limit) : null;
47
48 20
        return $this->CountDaftNestedObjectTreeFromArgs($left, $right, $limit, $withRoot);
49
    }
50
51 28
    public function RecallDaftNestedObjectTreeWithId(
52
        $id,
53
        bool $withRoot,
54
        ? int $limit
55
    ) : array {
56 28
        $object = $this->RecallDaftObject($id);
57
58
        return
59 28
            ($object instanceof DaftNestedObject)
60 4
                ? $this->RecallDaftNestedObjectTreeWithObject(
61 4
                    $object,
62 4
                    $withRoot,
63 4
                    $limit
64
                )
65
                : (
66 24
                    ((array) $id === (array) $this->GetNestedObjectTreeRootId())
67 24
                        ? $this->RecallDaftNestedObjectFullTree(0)
68 28
                        : []
69
                );
70
    }
71
72 4
    public function CountDaftNestedObjectTreeWithId(
73
        $id,
74
        bool $withRoot,
75
        ? int $limit
76
    ) : int {
77 4
        $object = $this->RecallDaftObject($id);
78
79
        return
80 4
            ($object instanceof DaftNestedObject)
81 4
                ? $this->CountDaftNestedObjectTreeWithObject(
82 4
                    $object,
83 4
                    $withRoot,
84 4
                    $limit
85
                )
86
                : (
87 4
                    ((array) $id === (array) $this->GetNestedObjectTreeRootId())
88 4
                        ? $this->CountDaftNestedObjectFullTree($limit)
89 4
                        : 0
90
                );
91
    }
92
93 4
    public function RecallDaftNestedObjectPathToObject(
94
        DaftNestedObject $leaf,
95
        bool $includeLeaf
96
    ) : array {
97 4
        return $this->RecallDaftNestedObjectTreeFromArgs(
98 4
            $leaf->GetIntNestedLeft(),
99 4
            $leaf->GetIntNestedRight(),
100 4
            null,
101 4
            $includeLeaf,
102 4
            false
103
        );
104
    }
105
106 4
    public function CountDaftNestedObjectPathToObject(
107
        DaftNestedObject $leaf,
108
        bool $includeLeaf
109
    ) : int {
110 4
        return $this->CountDaftNestedObjectTreeFromArgs(
111 4
            $leaf->GetIntNestedLeft(),
112 4
            $leaf->GetIntNestedRight(),
113 4
            null,
114 4
            $includeLeaf,
115 4
            false
116
        );
117
    }
118
119 4
    public function RecallDaftNestedObjectPathToId($id, bool $includeLeaf) : array
120
    {
121 4
        $object = $this->RecallDaftObject($id);
122
123
        return
124 4
            ($object instanceof DaftNestedObject)
125 4
                ? $this->RecallDaftNestedObjectPathToObject($object, $includeLeaf)
126 4
                : [];
127
    }
128
129 4
    public function CountDaftNestedObjectPathToId($id, bool $includeLeaf) : int
130
    {
131 4
        $object = $this->RecallDaftObject($id);
132
133
        return
134 4
            ($object instanceof DaftNestedObject)
135 4
                ? $this->CountDaftNestedObjectPathToObject($object, $includeLeaf)
136 4
                : 0;
137
    }
138
139 24
    public function CompareObjects(DaftNestedObject $a, DaftNestedObject $b) : int
140
    {
141 24
        return $a->GetIntNestedSortOrder() <=> $b->GetIntNestedSortOrder();
142
    }
143
144 50
    public static function DaftObjectRepositoryByType(
145
        string $type,
146
        ? EasyDB $db = null
147
    ) : DaftObjectRepository {
148 50
        if (is_a(static::class, DaftNestedWriteableObjectTree::class, true)) {
149 38
            if ( ! is_a($type, DaftNestedWriteableObject::class, true)) {
150 10
                throw new DaftObjectRepositoryTypeByClassMethodAndTypeException(
151 10
                    1,
152 10
                    static::class,
153 10
                    __FUNCTION__,
154 10
                    DaftNestedWriteableObject::class,
155 38
                    $type
156
                );
157
            }
158 12
        } elseif ( ! is_a($type, DaftNestedObject::class, true)) {
159 10
            throw new DaftObjectRepositoryTypeByClassMethodAndTypeException(
160 10
                1,
161 10
                static::class,
162 10
                __FUNCTION__,
163 10
                DaftNestedObject::class,
164 10
                $type
165
            );
166
        }
167
168 30
        return parent::DaftObjectRepositoryByType($type, $db);
169
    }
170
171 40
    protected function RememberDaftObjectData(DefinesOwnIdPropertiesInterface $object) : void
172
    {
173 40
        static::ThrowIfNotType($object, DaftNestedObject::class, 1, __METHOD__);
174
175 40
        parent::RememberDaftObjectData($object);
176 40
    }
177
178 28
    final protected function SelectingQueryDaftNestedObjectTreeFromArgs(bool $recall) : string
179
    {
180 28
        if ($recall) {
181
            /**
182
            * @var string[] $props
183
            */
184 28
            $props = $this->type::DaftObjectIdProperties();
185
186 28
            return implode(', ', array_map(
187
                function (string $prop) : string {
188 28
                    return $this->db->escapeIdentifier($prop);
189 28
                },
190 28
                $props
191
            ));
192
        }
193
194 20
        return 'COUNT(*)';
195
    }
196
197
    /**
198
    * @param array<int, string> $filter
199
    */
200 28
    final protected function FilterQueryDaftNestedObjectTreeFromArgs(array $filter) : string
201
    {
202 28
        return (count($filter) > 0) ? (' WHERE ' . implode(' AND ', $filter)) : '';
203
    }
204
205 28
    protected function QueryDaftNestedObjectTreeFromArgs(
206
        bool $recall,
207
        ? int $left,
208
        ? int $right,
209
        ? int $limit,
210
        bool $withRoot,
211
        bool $treeNotPath = true
212
    ) : PDOStatement {
213 28
        $queryArgs = [];
214 28
        $filter = [];
215
216 28
        $leftOp = ($withRoot ? ' >= ' : ' > ');
217 28
        $rightOp = ($withRoot ? ' <= ' : ' < ');
218
219 28
        if ( ! $treeNotPath) {
220 4
            $a = $leftOp;
221 4
            $leftOp = $rightOp;
222 4
            $rightOp = $a;
223
        }
224
225 28
        $escapedLeft = $this->db->escapeIdentifier('intNestedLeft');
226
227
        $maybeArgs = [
228 28
            ($escapedLeft . $leftOp . ' ?') => $left,
229 28
            ($this->db->escapeIdentifier('intNestedRight') . $rightOp . ' ?') => $right,
230 28
            ($this->db->escapeIdentifier('intNestedLevel') . ' <= ?') => $limit,
231
        ];
232
233 28
        foreach (array_filter($maybeArgs, 'is_int') as $filterStr => $queryArgVar) {
234 28
            $queryArgs[] = $queryArgVar;
235 28
            $filter[] = $filterStr;
236
        }
237
238
        $query =
239
            'SELECT ' .
240 28
            $this->SelectingQueryDaftNestedObjectTreeFromArgs($recall) .
241 28
            ' FROM ' .
242 28
            $this->db->escapeIdentifier($this->DaftObjectDatabaseTable()) .
243 28
            $this->FilterQueryDaftNestedObjectTreeFromArgs($filter) .
244 28
            ' ORDER BY ' .
245 28
            $escapedLeft;
246
247 28
        $sth = $this->db->prepare($query);
248
249 28
        $sth->execute($queryArgs);
250
251 28
        return $sth;
252
    }
253
254 28
    protected function RecallDaftNestedObjectTreeFromArgs(
255
        ? int $left,
256
        ? int $right,
257
        ? int $limit,
258
        bool $withRoot,
259
        bool $treeNotPath = true
260
    ) : array {
261 28
        $sth = $this->QueryDaftNestedObjectTreeFromArgs(
262 28
            true,
263 28
            $left,
264 28
            $right,
265 28
            $limit,
266 28
            $withRoot,
267 28
            $treeNotPath
268
        );
269
270 28
        return array_filter(
271 28
            array_map([$this, 'RecallDaftObject'], $sth->fetchAll(PDO::FETCH_NUM)),
272
            function (? DaftObject $maybe) : bool {
273 28
                return $maybe instanceof DaftNestedObject;
274 28
            }
275
        );
276
    }
277
278 20
    protected function CountDaftNestedObjectTreeFromArgs(
279
        ? int $left,
280
        ? int $right,
281
        ? int $limit,
282
        bool $withRoot,
283
        bool $treeNotPath = true
284
    ) : int {
285 20
        $sth = $this->QueryDaftNestedObjectTreeFromArgs(
286 20
            false,
287 20
            $left,
288 20
            $right,
289 20
            $limit,
290 20
            $withRoot,
291 20
            $treeNotPath
292
        );
293
294 20
        return (int) $sth->fetchColumn();
295
    }
296
}
297