1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Modules\Entitizer\Utils { |
4
|
|
|
|
5
|
|
|
use Modules\Entitizer, DB; |
6
|
|
|
|
7
|
|
|
abstract class Treeview extends Collection { |
8
|
|
|
|
9
|
|
|
# Get join statement |
10
|
|
|
|
11
|
|
|
protected function getQueryJoin(int $parent_id) { |
12
|
|
|
|
13
|
|
|
return (0 !== $parent_id) ? (("JOIN " . static::$table_relations . " rel ") . |
14
|
|
|
|
15
|
|
|
("ON rel.ancestor = " . $parent_id . " AND rel.descendant = ent.id AND rel.depth >= 1")) : |
16
|
|
|
|
17
|
|
|
("JOIN " . static::$table_relations . " rel ON rel.descendant = ent.id"); |
18
|
|
|
} |
19
|
|
|
|
20
|
|
|
# Get select query |
21
|
|
|
|
22
|
|
|
private function getSelectQuery(int $parent_id, array $config, array $order_by) { |
23
|
|
|
|
24
|
|
|
return ("SELECT " . $this->getSelection() . ", COALESCE(par.ancestor, 0) as parent_id ") . |
25
|
|
|
|
26
|
|
|
("FROM " . static::$table . " ent " . $this->getQueryJoin($parent_id) . " ") . |
27
|
|
|
|
28
|
|
|
("LEFT JOIN " . static::$table_relations . " par ON par.descendant = ent.id AND par.depth = 1 ") . |
29
|
|
|
|
30
|
|
|
(('' !== ($condition = $this->getCondition($config))) ? ("WHERE " . $condition . " ") : "") . |
31
|
|
|
|
32
|
|
|
("GROUP BY ent.id ORDER BY MAX(rel.depth) ASC, " . $this->getOrderBy($order_by)); |
33
|
|
|
} |
34
|
|
|
|
35
|
|
|
# Get count query |
36
|
|
|
|
37
|
|
|
private function getCountQuery(int $parent_id) { |
38
|
|
|
|
39
|
|
|
return ("SELECT COUNT(DISTINCT ent.id) as count FROM " . static::$table . " ent ") . |
40
|
|
|
|
41
|
|
|
$this->getQueryJoin($parent_id); |
42
|
|
|
} |
43
|
|
|
|
44
|
|
|
# Get depth query |
45
|
|
|
|
46
|
|
|
private function getDepthQuery(int $parent_id) { |
47
|
|
|
|
48
|
|
|
$query = ("SELECT COUNT(DISTINCT rel.depth) as depth FROM " . static::$table . " ent ") . |
49
|
|
|
|
50
|
|
|
$this->getQueryJoin($parent_id); |
51
|
|
|
|
52
|
|
|
# ------------------------ |
53
|
|
|
|
54
|
|
|
return $query; |
55
|
|
|
} |
56
|
|
|
|
57
|
|
|
# Get subtree |
58
|
|
|
|
59
|
|
|
public function subtree(int $parent_id = 0, array $config = [], array $order_by = []) { |
60
|
|
|
|
61
|
|
|
if (!(static::$nesting && ($parent_id >= 0))) return false; |
62
|
|
|
|
63
|
|
|
# Select entities |
64
|
|
|
|
65
|
|
|
$query = $this->getSelectQuery($parent_id, $config, $order_by); |
66
|
|
|
|
67
|
|
|
if (!(DB::send($query) && DB::last()->status)) return false; |
68
|
|
|
|
69
|
|
|
# Process results |
70
|
|
|
|
71
|
|
|
$items = [$parent_id => ['children' => []]]; |
72
|
|
|
|
73
|
|
|
while (null !== ($data = DB::last()->row())) { |
74
|
|
|
|
75
|
|
|
$dataset = Entitizer::dataset(static::$table, $data); |
76
|
|
|
|
77
|
|
|
$items[$dataset->id] = ['dataset' => $dataset, 'children' => []]; |
78
|
|
|
|
79
|
|
|
$items[intval($data['parent_id'])]['children'][] = $dataset->id; |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
# ------------------------ |
83
|
|
|
|
84
|
|
|
return $items; |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
# Get subtree count |
88
|
|
|
|
89
|
|
View Code Duplication |
public function subtreeCount(int $parent_id = 0) { |
|
|
|
|
90
|
|
|
|
91
|
|
|
if (!(static::$nesting && ($parent_id >= 0))) return false; |
92
|
|
|
|
93
|
|
|
# Get count |
94
|
|
|
|
95
|
|
|
$query = $this->getCountQuery($parent_id); |
96
|
|
|
|
97
|
|
|
if (!(DB::send($query) && DB::last()->status)) return false; |
98
|
|
|
|
99
|
|
|
# ------------------------ |
100
|
|
|
|
101
|
|
|
return intval(DB::last()->row()['count']); |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
# Get subtree depth |
105
|
|
|
|
106
|
|
View Code Duplication |
public function subtreeDepth(int $parent_id = 0) { |
|
|
|
|
107
|
|
|
|
108
|
|
|
if (!(static::$nesting && ($parent_id >= 0))) return false; |
109
|
|
|
|
110
|
|
|
# Get depth |
111
|
|
|
|
112
|
|
|
$query = $this->getDepthQuery($parent_id); |
113
|
|
|
|
114
|
|
|
if (!(DB::send($query) && DB::last()->status)) return false; |
115
|
|
|
|
116
|
|
|
# ------------------------ |
117
|
|
|
|
118
|
|
|
return intval(DB::last()->row()['depth']); |
119
|
|
|
} |
120
|
|
|
|
121
|
|
|
# Get path |
122
|
|
|
|
123
|
|
|
public function path(int $parent_id = 0) { |
124
|
|
|
|
125
|
|
|
if (!(static::$nesting && ($parent_id >= 0))) return false; |
126
|
|
|
|
127
|
|
|
# Process query |
128
|
|
|
|
129
|
|
|
$query = ("SELECT " . $this->getSelection() . " FROM " . static::$table . " ent ") . |
130
|
|
|
|
131
|
|
|
("JOIN " . static::$table_relations . " rel ON rel.ancestor = ent.id ") . |
132
|
|
|
|
133
|
|
|
("WHERE rel.descendant = " . $parent_id . " ORDER BY rel.depth DESC"); |
134
|
|
|
|
135
|
|
|
# Select path |
136
|
|
|
|
137
|
|
|
if (!(DB::send($query) && DB::last()->status)) return false; |
138
|
|
|
|
139
|
|
|
# Process results |
140
|
|
|
|
141
|
|
|
$path = []; |
142
|
|
|
|
143
|
|
|
while (null !== ($data = DB::last()->row())) $path[] = Entitizer::dataset(static::$table, $data)->data(); |
144
|
|
|
|
145
|
|
|
# ------------------------ |
146
|
|
|
|
147
|
|
|
return $path; |
148
|
|
|
} |
149
|
|
|
} |
150
|
|
|
} |
151
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.