ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
class.ilObjOrgUnitTree.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
3 require_once("./Modules/OrgUnit/classes/class.ilObjOrgUnit.php");
4 
14 
18  protected static $temporary_table_name = null;
22  private static $instance;
26  private $roles;
30  private $role_to_orgu;
34  private $staff;
38  private $tree_childs;
42  private $parent;
46  private $db;
47 
48 
49  private function __construct() {
50  global $DIC;
51  $ilDB = $DIC['ilDB'];
52  $tree = $DIC['tree'];
53  $this->db = $ilDB;
54  $this->tree = $tree;
55  $this->roles = array();
56  $this->staff = array();
57  }
58 
59 
63  public static function _getInstance() {
64  if (self::$instance === null) {
65  self::$instance = new self();
66  }
67 
68  return self::$instance;
69  }
70 
71 
77  public function getEmployees($ref_id, $recursive = false) {
78  return array_unique(($recursive ? $this->loadStaffRecursive("employee", $ref_id) : $this->loadStaff("employee", $ref_id)));
79  }
80 
81 
87  public function getSuperiors($ref_id, $recursive = false) {
88  return array_unique(($recursive ? $this->loadStaffRecursive("superior", $ref_id) : $this->loadStaff("superior", $ref_id)));
89  }
90 
91 
97  private function loadStaff($title, $ref_id) {
98  return $this->loadArrayOfStaff($title, array( $ref_id ));
99  }
100 
101 
102  private function loadStaffRecursive($title, $ref_id) {
103  return $this->loadArrayOfStaff($title, $this->getAllChildren($ref_id));
104  }
105 
106 
112  private function loadArrayOfStaff($title, $ref_ids) {
113  $this->loadRoles($title);
114  $all_refs = $ref_ids;
115  //take away ref_ids that are already loaded.
116  foreach ($ref_ids as $id => $ref_id) {
117  if (isset($this->staff[$title][$ref_id])) {
118  unset($ref_ids[$id]);
119  } else {
120  $this->staff[$title][$ref_id] = array();
121  $ref_ids[$id] = $this->roles[$title][$ref_id];
122  }
123  }
124 
125  //if there are still refs that need to be loaded, then do so.
126  if (count($ref_ids)) {
127  $q = "SELECT usr_id, rol_id FROM rbac_ua WHERE " . $this->db->in("rol_id", $ref_ids, false, "integer");
128  $set = $this->db->query($q);
129  while ($res = $this->db->fetchAssoc($set)) {
130  $orgu_ref = $this->role_to_orgu[$title][$res["rol_id"]];
131  $this->staff[$title][$orgu_ref][] = $res["usr_id"];
132  }
133  }
134 
135  //collect * users.
136  $all_users = array();
137  foreach ($all_refs as $ref) {
138  $all_users = array_merge($all_users, $this->staff[$title][$ref]);
139  }
140 
141  return $all_users;
142  }
143 
144 
149  public function getAllChildren($ref_id) {
150  $open = array( $ref_id );
151  $closed = array();
152  while (count($open)) {
153  $ref = array_pop($open);
154  $closed[] = $ref;
155  foreach ($this->getChildren($ref) as $child) {
156  if (!in_array($child, $open) && !in_array($child, $closed)) {
157  $open[] = $child;
158  }
159  }
160  }
161 
162  return $closed;
163  }
164 
165 
172  public function getOrgusWhereUserHasPermissionForOperation($operation) {
173  global $DIC;
174  $ilUser = $DIC['ilUser'];
175  /*$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
176  INNER JOIN rbac_operations ON rbac_operations.operation = ".$this->db->quote($operation, "text")."
177  INNER JOIN rbac_ua ON rbac_ua.usr_id = ".$this->db->quote($ilUser->getId(), "integer")."
178  INNER JOIN rbac_pa ON rbac_pa.rol_id = rbac_ua.rol_id AND rbac_pa.ops_id LIKE CONCAT('%', rbac_operations.ops_id, '%')
179  INNER JOIN rbac_fa ON rbac_fa.rol_id = rbac_ua.rol_id
180  INNER JOIN tree ON tree.child = rbac_fa.parent
181  INNER JOIN object_reference ON object_reference.ref_id = tree.parent
182  WHERE object_data.obj_id = object_reference.obj_id AND object_data.type = 'orgu'";*/
183 
184  $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
185  INNER JOIN rbac_operations ON rbac_operations.operation = " . $this->db->quote($operation, "text") . "
186  INNER JOIN rbac_ua ON rbac_ua.usr_id = " . $this->db->quote($ilUser->getId(), "integer") . "
187  INNER JOIN rbac_pa ON rbac_pa.rol_id = rbac_ua.rol_id AND rbac_pa.ops_id LIKE CONCAT('%', rbac_operations.ops_id, '%')
188  INNER JOIN object_reference ON object_reference.ref_id = rbac_pa.ref_id
189  WHERE object_data.obj_id = object_reference.obj_id AND object_data.type = 'orgu'";
190 
191  $set = $this->db->query($q);
192  $orgus = array();
193  while ($res = $this->db->fetchAssoc($set)) {
194  //this is needed as the table rbac_operations is not in the first normal form, thus this needs some additional checkings.
195  $perm_check = unserialize($res['ops_id']);
196  if (!in_array($res["op_id"], $perm_check)) {
197  continue;
198  }
199 
200  $orgus[] = $res["ref_id"];
201  }
202 
203  return $orgus;
204  }
205 
206 
214  public function getOrgusWhereUserHasPermissionForOperationId($operation_id) {
215  global $DIC;
216  $ilUser = $DIC['ilUser'];
217  $q = "SELECT object_data.obj_id, object_data.title, object_data.type, rbac_pa.ops_id FROM object_data
218  INNER JOIN rbac_ua ON rbac_ua.usr_id = " . $this->db->quote($ilUser->getId(), "integer") . "
219  INNER JOIN rbac_pa ON rbac_pa.rol_id = rbac_ua.rol_id AND rbac_pa.ops_id LIKE CONCAT('%', " . $this->db->quote($operation_id, "integer") . ", '%')
220  INNER JOIN rbac_fa ON rbac_fa.rol_id = rbac_ua.rol_id
221  INNER JOIN tree ON tree.child = rbac_fa.parent
222  INNER JOIN object_reference ON object_reference.ref_id = tree.parent
223  WHERE object_data.obj_id = object_reference.obj_id AND object_data.type = 'orgu'";
224 
225  $set = $this->db->query($q);
226  $orgus = array();
227  while ($res = $this->db->fetchAssoc($set)) {
228  //this is needed as the table rbac_operations is not in the first normal form, thus this needs some additional checkings.
229  $perm_check = unserialize($res['ops_id']);
230  if (!in_array($res["ops_id"], $perm_check)) {
231  continue;
232  }
233 
234  $orgus[] = $res["obj_id"];
235  }
236 
237  return $orgus;
238  }
239 
240 
245  private function getChildren($ref_id) {
246  $this->loadChildren($ref_id);
247 
248  return $this->tree_childs[$ref_id];
249  }
250 
251 
255  private function loadChildren($ref_id) {
256  if (!$this->tree_childs[$ref_id]) {
257  $children = array();
258  foreach ($this->tree->getChilds($ref_id) as $child) {
259  if ($child["type"] == "orgu") {
260  $children[] = $child["child"];
261  }
262  }
263  $this->tree_childs[$ref_id] = $children;
264  };
265  }
266 
267 
272  public function getAllOrgunitsOnLevelX($level) {
273  $levels = array( 0 => array( ilObjOrgUnit::getRootOrgRefId() ) );
274  $current_level = 0;
275  while ($current_level < $level) {
276  $new_level = array();
277  foreach ($levels[$current_level] as $orgu_ref) {
278  $new_level = array_merge($this->getChildren($orgu_ref), $new_level);
279  }
280  $new_level = array_unique($new_level);
281  $levels[$current_level + 1] = $new_level;
282  $current_level ++;
283  }
284 
285  return $levels[$level];
286  }
287 
288 
294  public function getEmployeesUnderUser($user_id, $recursive = true) {
295  //querry for all orgu where user_id is superior.
296  $q = "SELECT orgu.obj_id, refr.ref_id FROM object_data orgu
297  INNER JOIN object_reference refr ON refr.obj_id = orgu.obj_id
298  INNER JOIN object_data roles ON roles.title LIKE CONCAT('il_orgu_superior_',refr.ref_id)
299  INNER JOIN rbac_ua rbac ON rbac.usr_id = " . $this->db->quote($user_id, "integer") . " AND roles.obj_id = rbac.rol_id
300  WHERE orgu.type = 'orgu'";
301  $set = $this->db->query($q);
302  $orgu_ref_ids = array();
303  while ($res = $this->db->fetchAssoc($set)) {
304  $orgu_ref_ids[] = $res['ref_id'];
305  }
306  $employees = array();
307  foreach ($orgu_ref_ids as $orgu_ref_id) {
308  $employees = array_merge($employees, $this->getEmployees($orgu_ref_id, $recursive));
309  }
310 
311  return $employees;
312  }
313 
314 
320  public function getSuperiorsOfUser($user_id, $recursive = true) {
321  //querry for all orgu where user_id is superior.
322  $q = "SELECT orgu.obj_id, refr.ref_id FROM object_data orgu
323  INNER JOIN object_reference refr ON refr.obj_id = orgu.obj_id
324  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)
325  INNER JOIN rbac_ua rbac ON rbac.usr_id = " . $this->db->quote($user_id, "integer") . " AND roles.obj_id = rbac.rol_id
326  WHERE orgu.type = 'orgu'";
327  $set = $this->db->query($q);
328  $orgu_ref_ids = array();
329  while ($res = $this->db->fetchAssoc($set)) {
330  $orgu_ref_ids[] = $res['ref_id'];
331  }
332  $superiors = array();
333  foreach ($orgu_ref_ids as $orgu_ref_id) {
334  $superiors = array_merge($superiors, $this->getSuperiors($orgu_ref_id, $recursive));
335  }
336 
337  return $superiors;
338  }
339 
340 
349  public function getLevelXOfUser($user_id, $level) {
350  $q = "SELECT object_reference.ref_id FROM rbac_ua
351  JOIN rbac_fa ON rbac_fa.rol_id = rbac_ua.rol_id
352  JOIN object_reference ON rbac_fa.parent = object_reference.ref_id
353  JOIN object_data ON object_data.obj_id = object_reference.obj_id
354  WHERE rbac_ua.usr_id = " . $this->db->quote($user_id, 'integer') . " AND object_data.type = 'orgu';";
355 
356  $set = $this->db->query($q);
357  $orgu_ref_ids = array();
358  while ($res = $this->db->fetchAssoc($set)) {
359  $orgu_ref_ids[] = $res['ref_id'];
360  }
361  $orgus_on_level_x = array();
362  foreach ($orgu_ref_ids as $orgu_ref_id) {
363  try {
364  $orgus_on_level_x[] = $this->getLevelXOfTreenode($orgu_ref_id, $level);
365  } catch (Exception $e) {
366  // this means the user is assigned to a orgu above the given level. just dont add it to the list.
367  }
368  }
369 
370  return array_unique($orgus_on_level_x);
371  }
372 
373 
381  public function getOrgUnitOfUser($user_id, $ref_id = 0) {
382  $q = "SELECT object_reference.ref_id FROM rbac_ua
383  JOIN rbac_fa ON rbac_fa.rol_id = rbac_ua.rol_id
384  JOIN object_reference ON rbac_fa.parent = object_reference.ref_id
385  JOIN object_data ON object_data.obj_id = object_reference.obj_id
386  WHERE rbac_ua.usr_id = " . $this->db->quote($user_id, 'integer') . " AND object_data.type = 'orgu'";
387 
388  $set = $this->db->query($q);
389  $orgu_ref_ids = array();
390  while ($res = $this->db->fetchAssoc($set)) {
391  $orgu_ref_ids[] = $res['ref_id'];
392  }
393  $orgu_ref_ids = array_unique($orgu_ref_ids);
394  if ($ref_id) {
395  $childernOrgIds = $this->getAllChildren($ref_id);
396  foreach ($orgu_ref_ids as $k => $refId) {
397  if (!in_array($refId, $childernOrgIds)) {
398  unset($orgu_ref_ids[$k]);
399  }
400  }
401  }
402 
403  return $orgu_ref_ids;
404  }
405 
406 
422  public function buildTempTableWithUsrAssignements($temporary_table_name = 'orgu_usr_assignements') {
423  if (self::$temporary_table_name == $temporary_table_name) {
424  return true;
425  }
426  if (self::$temporary_table_name === null) {
428  self::$temporary_table_name = $temporary_table_name;
429  } elseif ($temporary_table_name != self::$temporary_table_name) {
430  throw new ilException('there is already a temporary table for org-unit assignement: ' . self::$temporary_table_name);
431  }
432 
433  $q = "CREATE TEMPORARY TABLE IF NOT EXISTS " . $temporary_table_name . " AS (
434  SELECT DISTINCT object_reference.ref_id AS ref_id, rbac_ua.usr_id AS user_id, orgu_path_storage.path AS path
435  FROM rbac_ua
436  JOIN rbac_fa ON rbac_fa.rol_id = rbac_ua.rol_id
437  JOIN object_reference ON rbac_fa.parent = object_reference.ref_id
438  JOIN object_data ON object_data.obj_id = object_reference.obj_id
439  JOIN orgu_path_storage ON orgu_path_storage.ref_id = object_reference.ref_id
440  WHERE object_data.type = 'orgu' AND object_reference.deleted IS NULL
441  );";
442  $this->db->manipulate($q);
443  return true;
444  }
445 
446 
452  if (self::$temporary_table_name === null || $temporary_table_name != self::$temporary_table_name) {
453  return false;
454  }
455  $q = "DROP TABLE IF EXISTS " . $temporary_table_name;
456  $this->db->manipulate($q);
457 
458  self::$temporary_table_name = null;
459 
460  return true;
461  }
462 
463 
468  public function getTitles($org_refs) {
469  $names = array();
470  foreach ($org_refs as $org_unit) {
471  $names[$org_unit] = ilObject::_lookupTitle(ilObject::_lookupObjId($org_unit));
472  }
473 
474  return $names;
475  }
476 
477 
481  public function getEmployeeRoles() {
482  $this->loadRoles("employee");
483 
484  return $this->roles["employee"];
485  }
486 
487 
491  public function getSuperiorRoles() {
492  $this->loadRoles("superior");
493 
494  return $this->roles["superior"];
495  }
496 
497 
501  private function loadRoles($role) {
502  if ($this->roles[$role] == null) {
503  $this->loadRolesQuery($role);
504  }
505  }
506 
507 
508  public function flushCache() {
509  $this->roles = null;
510  }
511 
512 
516  private function loadRolesQuery($role) {
517  $this->roles[$role] = array();
518  $q = "SELECT obj_id, title FROM object_data WHERE type = 'role' AND title LIKE 'il_orgu_" . $role . "%'";
519  $set = $this->db->query($q);
520  while ($res = $this->db->fetchAssoc($set)) {
521  $orgu_ref = $this->getRefIdFromRoleTitle($res["title"]);
522  $this->roles[$role][$orgu_ref] = $res["obj_id"];
523  $this->role_to_orgu[$role][$res["obj_id"]] = $orgu_ref;
524  }
525  }
526 
527 
532  private function getRefIdFromRoleTitle($role_title) {
533  $array = explode("_", $role_title);
534 
535  return $array[count($array) - 1];
536  }
537 
538 
557  public function getLevelXOfTreenode($orgu_ref, $level) {
558  $line = array( $orgu_ref );
559  $current_ref = $orgu_ref;
560  while ($current_ref != ilObjOrgUnit::getRootOrgRefId()) {
561  $current_ref = $this->getParent($current_ref);
562  if ($current_ref) {
563  $line[] = $current_ref;
564  } else {
565  break;
566  }
567  if (count($line) > 100) {
568  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");
569  }
570  }
571  $line = array_reverse($line);
572  if (count($line) > $level) {
573  return $line[$level];
574  } else {
575  throw new Exception("you want to fetch level " . $level . " but the line to the length of the line is only " . count($line)
576  . ". The line of the given org unit is: " . print_r($line, true));
577  }
578  }
579 
580 
585  public function getParent($orgu_ref) {
586  if (!$this->parent[$orgu_ref]) {
587  $this->parent[$orgu_ref] = $this->tree->getParentId($orgu_ref);
588  }
589 
590  return $this->parent[$orgu_ref];
591  }
592 }
getRefIdFromRoleTitle($role_title)
Base class for ILIAS Exception handling.
static _lookupTitle($a_id)
lookup object title
getSuperiorsOfUser($user_id, $recursive=true)
getOrgusWhereUserHasPermissionForOperationId($operation_id)
If you want to have all orgunits where the current user has the write permission: use this with the p...
getEmployees($ref_id, $recursive=false)
loadArrayOfStaff($title, $ref_ids)
static _lookupObjId($a_id)
getEmployeesUnderUser($user_id, $recursive=true)
getSuperiors($ref_id, $recursive=false)
loadStaffRecursive($title, $ref_id)
$ilUser
Definition: imgupload.php:18
Class ilObjOrgUnitTree Implements a singleton pattern for caching.
Create styles array
The data for the language used.
static getRootOrgRefId()
loadStaff($title, $ref_id)
getLevelXOfTreenode($orgu_ref, $level)
Specify eg.
$ref_id
Definition: sahs_server.php:39
global $ilDB
dropTempTable($temporary_table_name)
buildTempTableWithUsrAssignements($temporary_table_name='orgu_usr_assignements')
Creates a temporary table with all orgu/user assignements.
global $DIC
getLevelXOfUser($user_id, $level)
for additional info see the other getLevelX method.
getOrgusWhereUserHasPermissionForOperation($operation)
If you want to have all orgunits where the current user has the write permission: use this with the p...
getOrgUnitOfUser($user_id, $ref_id=0)
getOrgUnitOfUser