ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.ilObjOrgUnitTree.php
Go to the documentation of this file.
1<?php
2
26{
27 protected static ?string $temporary_table_name_getOrgUnitOfUser = null;
28 protected static ?string $temporary_table_name = null;
29 protected static ?ilObjOrgUnitTree $instance = null;
31 private array $roles;
33 private array $role_to_orgu;
35 private $staff;
37 private array $tree_childs = [];
39 private array $parent = [];
42 private \ilTree $tree;
43 protected \ilOrgUnitPositionDBRepository $positionRepo;
44 protected \ilOrgUnitUserAssignmentDBRepository $assignmentRepo;
45
46 private function __construct()
47 {
48 global $DIC;
49 $this->db = $DIC->database();
50 $this->tree = $DIC->repositoryTree();
51 $this->roles = array();
52 $this->staff = array();
53 $this->ilUser = $DIC->user();
54 }
55
56 public static function _getInstance(): \ilObjOrgUnitTree
57 {
58 if (static::$instance === null) {
59 static::$instance = new self();
60 }
61
62 return static::$instance;
63 }
64
66 {
67 if (!isset($this->positionRepo)) {
69 $this->positionRepo = $dic["repo.Positions"];
70 }
71
73 }
74
76 {
77 if (!isset($this->assignmentRepo)) {
79 $this->assignmentRepo = $dic["repo.UserAssignments"];
80 }
81
83 }
84
88 public function getAssignements(int $ref_id, ilOrgUnitPosition $ilOrgUnitPosition): array
89 {
90 return $this->getAssignedUsers([$ref_id], $ilOrgUnitPosition->getId());
91 }
92
97 public function getAssignedUsers(array $orgu_ids, int $position_id): array
98 {
99 return $this->getAssignmentRepo()->getUsersByOrgUnitsAndPosition($orgu_ids, $position_id);
100 }
101
106 public function getEmployees(int $ref_id, bool $recursive = false): array
107 {
108 $employee_position = $this->getPositionRepo()
109 ->getSingle(ilOrgUnitPosition::CORE_POSITION_EMPLOYEE, 'core_identifier')
110 ->getId();
111
112 if ($recursive === false) {
113 return $this->getAssignedUsers(
114 [$ref_id],
115 $employee_position
116 );
117 }
118
119 return $this->getAssignedUsers(
120 $this->getAllChildren($ref_id),
121 $employee_position
122 );
123 }
124
130 public function getSuperiors(int $ref_id, bool $recursive = false): array
131 {
132 $superior_position = $this->getPositionRepo()
133 ->getSingle(ilOrgUnitPosition::CORE_POSITION_SUPERIOR, 'core_identifier')
134 ->getId();
135
136 if ($recursive === false) {
137 return $this->getAssignedUsers(
138 [$ref_id],
139 $superior_position
140 );
141 }
142
143 return $this->getAssignedUsers(
144 $this->getAllChildren($ref_id),
145 $superior_position
146 );
147 }
148
154 private function loadArrayOfStaff(string $title, array $ref_ids): array
155 {
156 $this->loadRoles($title);
157 $all_refs = $ref_ids;
158 //take away ref_ids that are already loaded.
159 foreach ($ref_ids as $id => $ref_id) {
160 if (isset($this->staff[$title][$ref_id])) {
161 unset($ref_ids[$id]);
162 } else {
163 $this->staff[$title][$ref_id] = array();
164 $ref_ids[$id] = $this->roles[$title][$ref_id];
165 }
166 }
167
168 //if there are still refs that need to be loaded, then do so.
169 if (count($ref_ids)) {
170 $q = "SELECT usr_id, rol_id FROM rbac_ua WHERE " . $this->db->in("rol_id", $ref_ids, false, "integer");
171 $set = $this->db->query($q);
172 while ($res = $this->db->fetchAssoc($set)) {
173 $orgu_ref = $this->role_to_orgu[$title][$res["rol_id"]];
174 $this->staff[$title][$orgu_ref][] = $res["usr_id"];
175 }
176 }
177
178 //collect * users.
179 $all_users = [];
180 foreach ($all_refs as $ref) {
181 $all_users = array_merge($all_users, $this->staff[$title][$ref]);
182 }
183 return $all_users;
184 }
185
186 public function getAllChildren(int $ref_id): array
187 {
188 $open = array($ref_id);
189 $closed = array();
190 while (count($open)) {
191 $ref = array_pop($open);
192 $closed[] = $ref;
193 foreach ($this->getChildren($ref) as $child) {
194 if (in_array($child, $open, true) === false && in_array($child, $closed, true) === false) {
195 $open[] = $child;
196 }
197 }
198 }
199
200 return $closed;
201 }
202
208 public function getOrgusWhereUserHasPermissionForOperation($operation): array
209 {
210 /*$q = "SELECT object_data.obj_id, object_reference.ref_id, object_data.title, object_data.type, rbac_pa.ops_id, rbac_operations.ops_id as op_id FROM object_data
211 INNER JOIN rbac_operations ON rbac_operations.operation = ".$this->db->quote($operation, "text")."
212 INNER JOIN rbac_ua ON rbac_ua.usr_id = ".$this->db->quote($ilUser->getId(), "integer")."
213 INNER JOIN rbac_pa ON rbac_pa.rol_id = rbac_ua.rol_id AND rbac_pa.ops_id LIKE CONCAT('%', rbac_operations.ops_id, '%')
214 INNER JOIN rbac_fa ON rbac_fa.rol_id = rbac_ua.rol_id
215 INNER JOIN tree ON tree.child = rbac_fa.parent
216 INNER JOIN object_reference ON object_reference.ref_id = tree.parent
217 WHERE object_data.obj_id = object_reference.obj_id AND object_data.type = 'orgu'";*/
218
219 $q = "SELECT object_data.obj_id, object_reference.ref_id, object_data.title, object_data.type, rbac_pa.ops_id, rbac_operations.ops_id as op_id FROM object_data
220 INNER JOIN rbac_operations ON rbac_operations.operation = " . $this->db->quote($operation, "text") . "
221 INNER JOIN rbac_ua ON rbac_ua.usr_id = " . $this->db->quote($this->ilUser->getId(), "integer") . "
222 INNER JOIN rbac_pa ON rbac_pa.rol_id = rbac_ua.rol_id AND rbac_pa.ops_id LIKE CONCAT('%', rbac_operations.ops_id, '%')
223 INNER JOIN object_reference ON object_reference.ref_id = rbac_pa.ref_id
224 WHERE object_data.obj_id = object_reference.obj_id AND object_data.type = 'orgu'";
225
226 $set = $this->db->query($q);
227 $orgus = [];
228 while ($res = $this->db->fetchAssoc($set)) {
229 //this is needed as the table rbac_operations is not in the first normal form, thus this needs some additional checkings.
230 $perm_check = unserialize($res['ops_id'], ['allowed_classes' => true]);
231 if (in_array($res["op_id"], $perm_check, true) === false) {
232 continue;
233 }
234
235 $orgus[] = $res["ref_id"];
236 }
237
238 return $orgus;
239 }
240
246 public function getOrgusWhereUserHasPermissionForOperationId(string $operation_id): array
247 {
248 $q = "SELECT object_data.obj_id, object_data.title, object_data.type, rbac_pa.ops_id FROM object_data
249 INNER JOIN rbac_ua ON rbac_ua.usr_id = " . $this->db->quote($this->ilUser->getId(), "integer") . "
250 INNER JOIN rbac_pa ON rbac_pa.rol_id = rbac_ua.rol_id AND rbac_pa.ops_id LIKE CONCAT('%', " . $this->db->quote(
251 $operation_id,
252 "integer"
253 ) . ", '%')
254 INNER JOIN rbac_fa ON rbac_fa.rol_id = rbac_ua.rol_id
255 INNER JOIN tree ON tree.child = rbac_fa.parent
256 INNER JOIN object_reference ON object_reference.ref_id = tree.parent
257 WHERE object_data.obj_id = object_reference.obj_id AND object_data.type = 'orgu'";
258
259 $set = $this->db->query($q);
260 $orgus = array();
261 while ($res = $this->db->fetchAssoc($set)) {
262 //this is needed as the table rbac_operations is not in the first normal form, thus this needs some additional checkings.
263 $perm_check = unserialize($res['ops_id'], ['allowed_classes' => true]);
264 if (in_array($res["ops_id"], $perm_check, true) === false) {
265 continue;
266 }
267
268 $orgus[] = $res["obj_id"];
269 }
270
271 return $orgus;
272 }
273
274 private function getChildren(int $ref_id): array
275 {
276 $this->loadChildren($ref_id);
277 return $this->tree_childs[$ref_id];
278 }
279
280 private function loadChildren(int $ref_id): void
281 {
282 if (!array_key_exists($ref_id, $this->tree_childs)) {
283 $children = [];
284 foreach ($this->tree->getChilds($ref_id) as $child) {
285 if ($child["type"] == "orgu") {
286 $children[] = $child["child"];
287 }
288 }
289 $this->tree_childs[$ref_id] = $children;
290 }
291 }
292
293 public function getAllOrgunitsOnLevelX(int $level): array
294 {
295 $levels = array(0 => array(ilObjOrgUnit::getRootOrgRefId()));
296 $current_level = 0;
297 while ($current_level < $level) {
298 $new_level = array();
299 foreach ($levels[$current_level] as $orgu_ref) {
300 $new_level = array_merge($this->getChildren($orgu_ref), $new_level);
301 }
302 $new_level = array_unique($new_level);
303 $levels[$current_level + 1] = $new_level;
304 $current_level++;
305 }
306
307 return $levels[$level];
308 }
309
316 public function getEmployeesUnderUser(int $user_id, bool $recursive = true): array
317 {
318 $superior_position = $this->getPositionRepo()
319 ->getSingle(ilOrgUnitPosition::CORE_POSITION_SUPERIOR, 'core_identifier')
320 ->getId();
321 $employee_position = $this->getPositionRepo()
322 ->getSingle(ilOrgUnitPosition::CORE_POSITION_EMPLOYEE, 'core_identifier')
323 ->getId();
324
325 $orgu_ids = $this->getAssignmentRepo()
326 ->getOrgUnitsByUserAndPosition($user_id, $superior_position, $recursive);
327
328 return $this->getAssignedUsers(
329 $orgu_ids,
330 $employee_position
331 );
332 }
333
340 public function getSuperiorsOfUser(int $user_id, bool $recursive = true): array
341 {
342 //querry for all orgu where user_id is superior.
343 $q = "SELECT orgu.obj_id, refr.ref_id FROM object_data orgu
344 INNER JOIN object_reference refr ON refr.obj_id = orgu.obj_id
345 INNER JOIN object_data roles ON roles.title LIKE CONCAT('il_orgu_employee_',refr.ref_id) OR roles.title LIKE CONCAT('il_orgu_superior_',refr.ref_id)
346 INNER JOIN rbac_ua rbac ON rbac.usr_id = " . $this->db->quote($user_id, "integer") . " AND roles.obj_id = rbac.rol_id
347 WHERE orgu.type = 'orgu'";
348 $set = $this->db->query($q);
349 $orgu_ref_ids = array();
350 while ($res = $this->db->fetchAssoc($set)) {
351 $orgu_ref_ids[] = $res['ref_id'];
352 }
353 $superiors = array();
354 foreach ($orgu_ref_ids as $orgu_ref_id) {
355 $superiors = array_merge($superiors, $this->getSuperiors($orgu_ref_id, $recursive));
356 }
357
358 return $superiors;
359 }
360
366 public function getLevelXOfUser(int $user_id, int $level): array
367 {
368 $q = "SELECT object_reference.ref_id FROM rbac_ua
369 JOIN rbac_fa ON rbac_fa.rol_id = rbac_ua.rol_id
370 JOIN object_reference ON rbac_fa.parent = object_reference.ref_id
371 JOIN object_data ON object_data.obj_id = object_reference.obj_id
372 WHERE rbac_ua.usr_id = " . $this->db->quote($user_id, 'integer') . " AND object_data.type = 'orgu';";
373
374 $set = $this->db->query($q);
375 $orgu_ref_ids = array();
376 while ($res = $this->db->fetchAssoc($set)) {
377 $orgu_ref_ids[] = $res['ref_id'];
378 }
379 $orgus_on_level_x = array();
380 foreach ($orgu_ref_ids as $orgu_ref_id) {
381 try {
382 $orgus_on_level_x[] = $this->getLevelXOfTreenode($orgu_ref_id, $level);
383 } catch (Exception $e) {
384 // this means the user is assigned to a orgu above the given level. just dont add it to the list.
385 }
386 }
387
388 return array_unique($orgus_on_level_x);
389 }
390
394 public function getOrgUnitOfUser(int $user_id): array
395 {
396 return $this->getAssignmentRepo()->getOrgUnitsByUser($user_id);
397 }
398
411 public function buildTempTableWithUsrAssignements(string $temporary_table_name = 'orgu_usr_assignements'): bool
412 {
413 if (self::$temporary_table_name == $temporary_table_name) {
414 return true;
415 }
416 if (self::$temporary_table_name === null) {
417 $this->dropTempTable($temporary_table_name);
418 self::$temporary_table_name = $temporary_table_name;
419 } elseif ($temporary_table_name != self::$temporary_table_name) {
420 throw new ilException('there is already a temporary table for org-unit assignement: ' . self::$temporary_table_name);
421 }
422
423 $q = "CREATE TEMPORARY TABLE IF NOT EXISTS " . $temporary_table_name . " AS (
424 SELECT DISTINCT object_reference.ref_id AS ref_id, il_orgu_ua.user_id AS user_id, orgu_path_storage.path AS path
425 FROM il_orgu_ua
426 JOIN object_reference ON object_reference.ref_id = il_orgu_ua.orgu_id
427 JOIN object_data ON object_data.obj_id = object_reference.obj_id
428 JOIN orgu_path_storage ON orgu_path_storage.ref_id = object_reference.ref_id
429 WHERE object_data.type = 'orgu' AND object_reference.deleted IS NULL
430 );";
431 $this->db->manipulate($q);
432
433 return true;
434 }
435
436 public function dropTempTable(string $temporary_table_name): bool
437 {
438 if (self::$temporary_table_name === null
439 || $temporary_table_name !== self::$temporary_table_name
440 ) {
441 return false;
442 }
443 $q = "DROP TABLE IF EXISTS " . $temporary_table_name;
444 $this->db->manipulate($q);
445
446 self::$temporary_table_name = null;
447
448 return true;
449 }
450
451 public function getTitles(array $org_refs): array
452 {
453 $names = array();
454 foreach ($org_refs as $org_unit) {
455 $names[$org_unit] = ilObject::_lookupTitle(ilObject::_lookupObjId($org_unit));
456 }
457
458 return $names;
459 }
460
464 public function getEmployeeRoles(): array
465 {
466 $this->loadRoles("employee");
467 return $this->roles["employee"];
468 }
469
473 public function getSuperiorRoles(): array
474 {
475 $this->loadRoles("superior");
476
477 return $this->roles["superior"];
478 }
479
480 private function loadRoles(string $role)
481 {
482 if ($this->roles[$role] == null) {
483 $this->loadRolesQuery($role);
484 }
485 }
486
487 public function flushCache(): void
488 {
489 $this->roles = null;
490 }
491
492 private function loadRolesQuery(string $role): void
493 {
494 $this->roles[$role] = array();
495 $q = "SELECT obj_id, title FROM object_data WHERE type = 'role' AND title LIKE 'il_orgu_" . $role . "%'";
496 $set = $this->db->query($q);
497 while ($res = $this->db->fetchAssoc($set)) {
498 $orgu_ref = $this->getRefIdFromRoleTitle($res["title"]);
499 $this->roles[$role][$orgu_ref] = $res["obj_id"];
500 $this->role_to_orgu[$role][$res["obj_id"]] = $orgu_ref;
501 }
502 }
503
504 private function getRefIdFromRoleTitle(string $role_title): int
505 {
506 $array = explode("_", $role_title);
507
508 return $array[count($array) - 1];
509 }
510
527 public function getLevelXOfTreenode(int $orgu_ref, int $level)
528 {
529 $line = array($orgu_ref);
530 $current_ref = $orgu_ref;
531 while ($current_ref != ilObjOrgUnit::getRootOrgRefId()) {
532 $current_ref = $this->getParent($current_ref);
533 if ($current_ref) {
534 $line[] = $current_ref;
535 } else {
536 break;
537 }
538 if (count($line) > 100) {
539 throw new Exception("There's either a non valid call of the getLevelXOfTreenode in ilObjOrgUnitTree or your nesting of orgunits is higher than 100 units, which isn't encouraged");
540 }
541 }
542 $line = array_reverse($line);
543 if (count($line) > $level) {
544 return $line[$level];
545 } else {
546 throw new Exception("you want to fetch level " . $level . " but the line to the length of the line is only " . count($line)
547 . ". The line of the given org unit is: " . print_r($line, true));
548 }
549 }
550
551 public function getParent(int $orgu_ref): int
552 {
553 if (array_key_exists($orgu_ref, $this->parent) === false) {
554 $this->parent[$orgu_ref] = $this->tree->getParentId($orgu_ref);
555 }
556
557 return $this->parent[$orgu_ref];
558 }
559}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
Base class for ILIAS Exception handling.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static ilObjOrgUnitTree $instance
getTitles(array $org_refs)
getRefIdFromRoleTitle(string $role_title)
static string $temporary_table_name
ilOrgUnitUserAssignmentDBRepository $assignmentRepo
getEmployees(int $ref_id, bool $recursive=false)
getAllOrgunitsOnLevelX(int $level)
getOrgusWhereUserHasPermissionForOperation($operation)
If you want to have all orgunits where the current user has the write permission: use this with the p...
loadArrayOfStaff(string $title, array $ref_ids)
getLevelXOfTreenode(int $orgu_ref, int $level)
Specify eg.
getLevelXOfUser(int $user_id, int $level)
for additional info see the other getLevelX method.
buildTempTableWithUsrAssignements(string $temporary_table_name='orgu_usr_assignements')
Creates a temporary table with all orgu/user assignements.
getSuperiorsOfUser(int $user_id, bool $recursive=true)
dropTempTable(string $temporary_table_name)
getOrgusWhereUserHasPermissionForOperationId(string $operation_id)
If you want to have all orgunits where the current user has the write permission: use this with the p...
getAssignements(int $ref_id, ilOrgUnitPosition $ilOrgUnitPosition)
static string $temporary_table_name_getOrgUnitOfUser
getAssignedUsers(array $orgu_ids, int $position_id)
getOrgUnitOfUser(int $user_id)
getSuperiors(int $ref_id, bool $recursive=false)
ilOrgUnitPositionDBRepository $positionRepo
getEmployeesUnderUser(int $user_id, bool $recursive=true)
static getRootOrgRefId()
User class.
static _lookupObjId(int $ref_id)
static _lookupTitle(int $obj_id)
Class ilOrgUnitPosition.
Interface ilDBInterface.
$ref_id
Definition: ltiauth.php:66
$dic
Definition: ltiresult.php:33
$res
Definition: ltiservices.php:69
global $DIC
Definition: shib_login.php:26
$q
Definition: shib_logout.php:23