ILIAS  release_8 Revision v8.24
class.ilVirtualSkillTree.php
Go to the documentation of this file.
1<?php
2
29{
30 protected ilLanguage $lng;
31 protected ilSkillTree $tree;
32
36 protected static ?array $order_node_data = null;
37 protected bool $include_drafts = false;
38
42 protected array $drafts = [];
43 protected bool $include_outdated = false;
44
48 protected array $outdated = [];
49
50 public function __construct(int $tree_id)
51 {
52 global $DIC;
53
54 $this->lng = $DIC->language();
55 $this->tree = $DIC->skills()->internal()->factory()->tree()->getTreeById($tree_id);
56 }
57
61 public function getRootNode(): array
62 {
63 $root_id = $this->tree->readRootId();
64 $root_node = $this->tree->getNodeData($root_id);
65 unset($root_node["child"]);
66 $root_node["id"] = $root_id . ":0";
67 $root_node["cskill_id"] = $root_id . ":0";
68
69 return $root_node;
70 }
71
72 public function setIncludeDrafts(bool $a_val): void
73 {
74 $this->include_drafts = $a_val;
75 }
76
77 public function getIncludeDrafts(): bool
78 {
80 }
81
82 public function setIncludeOutdated(bool $a_val): void
83 {
84 $this->include_outdated = $a_val;
85 }
86
87 public function getIncludeOutdated(): bool
88 {
90 }
91
92 public function getNode(string $a_vtree_id): array
93 {
94 $id_parts = explode(":", $a_vtree_id);
95 $skl_tree_id = (int) $id_parts[0];
96 $skl_template_tree_id = isset($id_parts[1]) ? (int) $id_parts[1] : 0;
97
98 if ($skl_template_tree_id == 0
99 || (ilSkillTemplateReference::_lookupTemplateId($skl_tree_id) == $skl_template_tree_id)) {
100 $node_data = $this->tree->getNodeData($skl_tree_id);
101 if (isset($node_data["parent"])) {
102 $node_data["parent"] = $node_data["parent"] . ":0";
103 }
104 } else {
105 $node_data = $this->tree->getNodeData($skl_template_tree_id);
106 $node_data["parent"] = $skl_tree_id . ":" . $node_data["parent"];
107 }
108
109 unset($node_data["child"]);
110 unset($node_data["skl_tree_id"]);
111 unset($node_data["lft"]);
112 unset($node_data["rgt"]);
113 unset($node_data["depth"]);
114
115 $node_data["id"] = $a_vtree_id;
116 $cid = $this->getCSkillIdForVTreeId($a_vtree_id);
117 $cid_parts = explode(":", $cid);
118 $node_data["skill_id"] = $cid_parts[0];
119 $node_data["tref_id"] = $cid_parts[1];
120 $node_data["cskill_id"] = $cid;
121
122 return $node_data;
123 }
124
128 public function getChildsOfNode(string $a_parent_id): array
129 {
130 $a_parent_id_parts = explode(":", $a_parent_id);
131 $a_parent_skl_tree_id = (int) $a_parent_id_parts[0];
132 $a_parent_skl_template_tree_id = isset($a_parent_id_parts[1]) ? (int) $a_parent_id_parts[1] : 0;
133
134 if ($a_parent_skl_template_tree_id == 0) {
135 $childs = $this->tree->getChildsByTypeFilter($a_parent_skl_tree_id, array("scat", "skll", "sktr"), "order_nr");
136 } else {
137 $childs = $this->tree->getChildsByTypeFilter($a_parent_skl_template_tree_id, array("sktp", "sctp"), "order_nr");
138 }
139
140 $drafts = [];
141 $outdated = [];
142 foreach ($childs as $k => $c) {
143 if ($a_parent_skl_template_tree_id > 0) {
144 // we are in template tree only
145 $child_id = $a_parent_skl_tree_id . ":" . $c["child"];
146 } elseif (!in_array($c["type"], array("sktr", "sctr"))) {
147 // we are in main tree only
148 $child_id = $c["child"] . ":0";
149 } else {
150 // get template id for references
151 $child_id = $c["child"] . ":" . ilSkillTemplateReference::_lookupTemplateId($c["child"]);
152 }
153 unset($childs[$k]["child"]);
154 unset($childs[$k]["skl_tree_id"]);
155 unset($childs[$k]["lft"]);
156 unset($childs[$k]["rgt"]);
157 unset($childs[$k]["depth"]);
158 $childs[$k]["id"] = $child_id;
159 $cid = $this->getCSkillIdForVTreeId($child_id);
160 $cid_parts = explode(":", $cid);
161 $childs[$k]["skill_id"] = $cid_parts[0];
162 $childs[$k]["tref_id"] = $cid_parts[1];
163 $childs[$k]["cskill_id"] = $cid;
164 $childs[$k]["parent"] = $a_parent_id;
165
166 // @todo: prepare this for tref id?
168 in_array($a_parent_id, $this->drafts)) {
169 $this->drafts[] = $child_id;
170 $drafts[] = $k;
171 }
173 in_array($a_parent_id, $this->outdated)) {
174 $this->outdated[] = $child_id;
175 $outdated[] = $k;
176 }
177 }
178 if (!$this->getIncludeDrafts()) {
179 foreach ($drafts as $d) {
180 unset($childs[$d]);
181 }
182 }
183 if (!$this->getIncludeOutdated()) {
184 foreach ($outdated as $d) {
185 unset($childs[$d]);
186 }
187 }
188
189 return $childs;
190 }
191
192 public function getChildsOfNodeForCSkillId(string $a_cskill_id): array
193 {
194 $id_parts = explode(":", $a_cskill_id);
195 if (!isset($id_parts[1]) || $id_parts[1] == 0) {
196 $id = $id_parts[0] . ":0";
197 } else {
198 $id = $id_parts[1] . ":" . $id_parts[0];
199 }
200 return $this->getChildsOfNode($id);
201 }
202
203 public function getCSkillIdForVTreeId(string $a_vtree_id): string
204 {
205 $id_parts = explode(":", $a_vtree_id);
206 if (!isset($id_parts[1]) || $id_parts[1] == 0) {
207 // skill in main tree
208 $skill_id = $id_parts[0];
209 $tref_id = 0;
210 } else {
211 // skill in template
212 $tref_id = $id_parts[0];
213 $skill_id = $id_parts[1];
214 }
215 return $skill_id . ":" . $tref_id;
216 }
217
218 public function getVTreeIdForCSkillId(string $a_cskill_id): string
219 {
220 $id_parts = explode(":", $a_cskill_id);
221 if (!isset($id_parts[1]) || $id_parts[1] == 0) {
222 $id = $id_parts[0] . ":0";
223 } else {
224 $id = $id_parts[1] . ":" . $id_parts[0];
225 }
226 return $id;
227 }
228
229 public function getNodeTitle(array $a_node): string
230 {
232
233 $a_parent_id_parts = explode(":", $a_node["id"]);
234 $a_parent_skl_tree_id = (int) $a_parent_id_parts[0];
235 $a_parent_skl_template_tree_id = isset($a_parent_id_parts[1]) ? (int) $a_parent_id_parts[1] : 0;
236
237 // title
238 $title = $a_node["title"];
239
240 // root?
241 if ($a_node["type"] == "skrt") {
242 $lng->txt("skmg_skills");
243 } elseif ($a_node["type"] == "sktr") {
244 // $title.= " (".ilSkillTreeNode::_lookupTitle($a_parent_skl_template_tree_id).")";
245 }
246
247 return $title;
248 }
249
253 public function getSubTreeForCSkillId(string $a_cskill_id, bool $a_only_basic = false): array
254 {
255 $id_parts = explode(":", $a_cskill_id);
256 if (!isset($id_parts[1]) || $id_parts[1] == 0) {
257 $id = $id_parts[0] . ":0";
258 } else {
259 $id = $id_parts[1] . ":" . $id_parts[0];
260 }
261
262 $result = [];
263
264 $node = $this->getNode($id);
265 if (!$a_only_basic || isset($node["type"]) && in_array($node["type"], array("skll", "sktp")) ||
266 ($node["type"] == "sktr" && ilSkillTreeNode::_lookupType($node["skill_id"]) == "sktp")) {
267 $result[] = $node;
268 }
269 return array_merge($result, $this->__getSubTreeRec($id, $a_only_basic));
270 }
271
275 protected function __getSubTreeRec(string $id, bool $a_only_basic): array
276 {
277 $result = [];
278 $childs = $this->getChildsOfNode($id);
279 foreach ($childs as $c) {
280 if (!$a_only_basic || in_array($c["type"], array("skll", "sktp")) ||
281 ($c["type"] == "sktr" && ilSkillTreeNode::_lookupType($c["skill_id"]) == "sktp")) {
282 $result[] = $c;
283 }
284 $result = array_merge($result, $this->__getSubTreeRec((int) $c["id"], $a_only_basic));
285 }
286
287 return $result;
288 }
289
290 public function isDraft(string $a_node_id): bool
291 {
292 return in_array($a_node_id, $this->drafts);
293 }
294
295 public function isOutdated(string $a_node_id): bool
296 {
297 return in_array($a_node_id, $this->outdated);
298 }
299
308 public function getOrderedNodeset(array $c_skill_ids, string $a_skill_id_key = "", string $a_tref_id_key = ""): array
309 {
310 global $DIC;
311
312 $db = $DIC->database();
313
314 if (self::$order_node_data == null) {
315 $node_data = [];
316 $set = $db->query("SELECT t.child, t.parent, t.lft, n.order_nr FROM skl_tree t JOIN skl_tree_node n ON (t.child = n.obj_id)");
317 while ($rec = $db->fetchAssoc($set)) {
318 $node_data[(int) $rec["child"]] = array(
319 "parent" => null === $rec["parent"] ? null : (int) $rec["parent"],
320 "lft" => (int) $rec["lft"],
321 "order_nr" => (int) $rec["order_nr"],
322 );
323 }
324 self::$order_node_data = $node_data;
325 } else {
326 $node_data = self::$order_node_data;
327 }
328
329 uasort($c_skill_ids, function ($a, $b) use ($node_data, $a_skill_id_key, $a_tref_id_key): int {
330
331 // normalize to cskill strings
332 if (is_array($a)) {
333 $cskilla = $a[$a_skill_id_key] . ":" . $a[$a_tref_id_key];
334 $cskillb = $b[$a_skill_id_key] . ":" . $b[$a_tref_id_key];
335 } else {
336 $cskilla = $a;
337 $cskillb = $b;
338 }
339
340 // get vtree ids
341 $vida = explode(":", $this->getVTreeIdForCSkillId($cskilla));
342 $vidb = explode(":", $this->getVTreeIdForCSkillId($cskillb));
343
344 $ua = $this->getFirstUncommonAncestors($vida[0], $vidb[0], $node_data);
345 if (is_array($ua) && isset($node_data[$ua[0]]) && isset($node_data[$ua[1]])) {
346 return ($node_data[$ua[0]]["order_nr"] - $node_data[$ua[1]]["order_nr"]);
347 }
348 // if we did not find a first uncommon ancestor, we are in the same node in the
349 // main tree, here, if we have tref ids, we let the template tree decide
350 if ($vida[1] > 0 && $vidb[1] > 0) {
351 $ua = $this->getFirstUncommonAncestors($vida[1], $vidb[1], $node_data);
352 if (is_array($ua) && isset($node_data[$ua[0]]) && isset($node_data[$ua[1]])) {
353 return ($node_data[$ua[0]]["order_nr"] - $node_data[$ua[1]]["order_nr"]);
354 }
355 }
356
357 return 0;
358 });
359
360 return $c_skill_ids;
361 }
362
366 protected function getPath(string $a, array $node_data): array
367 {
368 $path[] = $a;
369 if (isset($node_data[$a]) && isset($node_data[$a]["parent"])) {
370 while ($node_data[$a]["parent"] != 0) {
371 $a = $node_data[$a]["parent"];
372 $path[] = $a;
373 }
374 }
375 return array_reverse($path);
376 }
377
383 protected function getFirstUncommonAncestors(string $a, string $b, array $node_data)
384 {
385 $path_a = $this->getPath($a, $node_data);
386 $path_b = $this->getPath($b, $node_data);
387 foreach ($path_a as $k => $v) {
388 if ($v != $path_b[$k]) {
389 return array($v, $path_b[$k]);
390 }
391 }
392 return false;
393 }
394}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
language handling
txt(string $a_topic, string $a_default_lang_fallback_mod="")
gets the text for a given topic if the topic is not in the list, the topic itself with "-" will be re...
static _lookupType(int $a_obj_id)
static _lookupStatus(int $a_obj_id)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getPath(string $a, array $node_data)
get path in node data
getChildsOfNodeForCSkillId(string $a_cskill_id)
isOutdated(string $a_node_id)
getNode(string $a_vtree_id)
__getSubTreeRec(string $id, bool $a_only_basic)
getVTreeIdForCSkillId(string $a_cskill_id)
getChildsOfNode(string $a_parent_id)
getOrderedNodeset(array $c_skill_ids, string $a_skill_id_key="", string $a_tref_id_key="")
Get ordererd nodeset for common skill ids.
getCSkillIdForVTreeId(string $a_vtree_id)
getFirstUncommonAncestors(string $a, string $b, array $node_data)
get first uncommon ancestors of $a and $b in $node_data
getSubTreeForCSkillId(string $a_cskill_id, bool $a_only_basic=false)
$c
Definition: cli.php:38
for( $i=6;$i< 13;$i++) for($i=1; $i< 13; $i++) $d
Definition: date.php:296
global $DIC
Definition: feed.php:28
$path
Definition: ltiservices.php:32
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples