ILIAS  Release_4_4_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups Pages
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");
14  private static $instance;
15 
17  private $roles;
18 
20  private $role_to_orgu;
21 
23  private $staff;
24 
26  private $tree_childs;
27 
29  private $ctrl;
30 
32  private $parent;
33 
35  private $db;
36 
38  private function __construct(){
39  global $ilCtrl, $ilDB, $tree;
40  $this->ctrl = $ilCtrl;
41  $this->db = $ilDB;
42  $this->tree = $tree;
43  $this->roles = array();
44  $this->staff = array();
45  }
46 
48  public static function _getInstance(){
49  if(self::$instance == null)
50  self::$instance = new ilObjOrgUnitTree();
51  return self::$instance;
52  }
53 
59  public function getEmployees($ref_id, $recursive = false){
60  return array_unique(($recursive?$this->loadStaffRecursive("employee",$ref_id):$this->loadStaff("employee", $ref_id)));
61  }
62 
63  public function getSuperiors($ref_id, $recursive = false){
64  return array_unique(($recursive?$this->loadStaffRecursive("superior",$ref_id):$this->loadStaff("superior", $ref_id)));
65  }
66 
72  private function loadStaff($title, $ref_id){
73  return $this->loadArrayOfStaff($title, array($ref_id));
74  }
75 
76  private function loadStaffRecursive($title, $ref_id){
77  return $this->loadArrayOfStaff($title, $this->getAllChildren($ref_id));
78  }
79 
85  private function loadArrayOfStaff($title, $ref_ids){
86  $this->loadRoles($title);
87  $all_refs = $ref_ids;
88  //take away ref_ids that are already loaded.
89  foreach($ref_ids as $id => $ref_id){
90  if(isset($this->staff[$title][$ref_id]))
91  unset($ref_ids[$id]);
92  else{
93  $this->staff[$title][$ref_id] = array();
94  $ref_ids[$id] = $this->roles[$title][$ref_id];
95  }
96  }
97 
98  //if there are still refs that need to be loaded, then do so.
99  if(count($ref_ids)){
100  $q = "SELECT usr_id, rol_id FROM rbac_ua WHERE ".$this->db->in("rol_id", $ref_ids, false, "integer");
101  $set = $this->db->query($q);
102  while($res = $this->db->fetchAssoc($set)){
103  $orgu_ref = $this->role_to_orgu[$title][$res["rol_id"]];
104  $this->staff[$title][$orgu_ref][] = $res["usr_id"];
105  }
106  }
107 
108  //collect * users.
109  $all_users = array();
110  foreach($all_refs as $ref)
111  $all_users = array_merge($all_users, $this->staff[$title][$ref]);
112 
113  return $all_users;
114  }
115 
116  public function getAllChildren($ref_id){
117  $open = array($ref_id);
118  $closed = array();
119  while(count($open)){
120  $ref = array_pop($open);
121  $closed[] = $ref;
122  foreach($this->getChildren($ref) as $child)
123  if(!in_array($child, $open) && ! in_array($child, $closed))
124  $open[] = $child;
125  }
126  return $closed;
127  }
128 
134  public function getOrgusWhereUserHasPermissionForOperation($operation){
135  global $ilUser;
136  /*$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
137  INNER JOIN rbac_operations ON rbac_operations.operation = ".$this->db->quote($operation, "text")."
138  INNER JOIN rbac_ua ON rbac_ua.usr_id = ".$this->db->quote($ilUser->getId(), "integer")."
139  INNER JOIN rbac_pa ON rbac_pa.rol_id = rbac_ua.rol_id AND rbac_pa.ops_id LIKE CONCAT('%', rbac_operations.ops_id, '%')
140  INNER JOIN rbac_fa ON rbac_fa.rol_id = rbac_ua.rol_id
141  INNER JOIN tree ON tree.child = rbac_fa.parent
142  INNER JOIN object_reference ON object_reference.ref_id = tree.parent
143  WHERE object_data.obj_id = object_reference.obj_id AND object_data.type = 'orgu'";*/
144 
145  $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
146  INNER JOIN rbac_operations ON rbac_operations.operation = ".$this->db->quote($operation, "text")."
147  INNER JOIN rbac_ua ON rbac_ua.usr_id = ".$this->db->quote($ilUser->getId(), "integer")."
148  INNER JOIN rbac_pa ON rbac_pa.rol_id = rbac_ua.rol_id AND rbac_pa.ops_id LIKE CONCAT('%', rbac_operations.ops_id, '%')
149  INNER JOIN object_reference ON object_reference.ref_id = rbac_pa.ref_id
150  WHERE object_data.obj_id = object_reference.obj_id AND object_data.type = 'orgu'";
151 
152  $set = $this->db->query($q);
153  $orgus = array();
154  while($res = $this->db->fetchAssoc($set)){
155  //this is needed as the table rbac_operations is not in the first normal form, thus this needs some additional checkings.
156  $perm_check = unserialize($res['ops_id']);
157  if(!in_array($res["op_id"], $perm_check))
158  continue;
159 
160  $orgus[] = $res["ref_id"];
161  }
162  return $orgus;
163  }
164 
170  public function getOrgusWhereUserHasPermissionForOperationId($operation_id){
171  global $ilUser;
172  $q = "SELECT object_data.obj_id, object_data.title, object_data.type, rbac_pa.ops_id FROM object_data
173  INNER JOIN rbac_ua ON rbac_ua.usr_id = ".$this->db->quote($ilUser->getId(), "integer")."
174  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").", '%')
175  INNER JOIN rbac_fa ON rbac_fa.rol_id = rbac_ua.rol_id
176  INNER JOIN tree ON tree.child = rbac_fa.parent
177  INNER JOIN object_reference ON object_reference.ref_id = tree.parent
178  WHERE object_data.obj_id = object_reference.obj_id AND object_data.type = 'orgu'";
179 
180  $set = $this->db->query($q);
181  $orgus = array();
182  while($res = $this->db->fetchAssoc($set)){
183  //this is needed as the table rbac_operations is not in the first normal form, thus this needs some additional checkings.
184  $perm_check = unserialize($res['ops_id']);
185  if(!in_array($res["ops_id"], $perm_check))
186  continue;
187 
188  $orgus[] = $res["obj_id"];
189  }
190  return $orgus;
191  }
192 
197  private function getChildren($ref_id){
198  $this->loadChildren($ref_id);
199  return $this->tree_childs[$ref_id];
200  }
201 
202  private function loadChildren($ref_id){
203  if(!$this->tree_childs[$ref_id]){
204  $children = array();
205  foreach($this->tree->getChilds($ref_id) as $child){
206  if($child["type"] == "orgu")
207  $children[] = $child["child"];
208  }
209  $this->tree_childs[$ref_id] = $children;
210  };
211  }
212 
213  public function getAllOrgunitsOnLevelX($level){
214  $levels = array(0 => array(ilObjOrgUnit::getRootOrgRefId()));
215  $current_level = 0;
216  while($current_level < $level){
217  $new_level = array();
218  foreach($levels[$current_level] as $orgu_ref)
219  $new_level = array_merge($this->getChildren($orgu_ref), $new_level);
220  $new_level = array_unique($new_level);
221  $levels[$current_level+1] = $new_level;
222  $current_level++;
223  }
224  return $levels[$level];
225  }
226 
232  public function getEmployeesUnderUser($user_id, $recursive = true){
233  //querry for all orgu where user_id is superior.
234  $q = "SELECT orgu.obj_id, refr.ref_id FROM object_data orgu
235  INNER JOIN object_reference refr ON refr.obj_id = orgu.obj_id
236  INNER JOIN object_data roles ON roles.title LIKE CONCAT('il_orgu_superior_',refr.ref_id)
237  INNER JOIN rbac_ua rbac ON rbac.usr_id = ".$this->db->quote($user_id, "integer")." AND roles.obj_id = rbac.rol_id
238  WHERE orgu.type = 'orgu'";
239  $set = $this->db->query($q);
240  $orgu_ref_ids = array();
241  while($res = $this->db->fetchAssoc($set)){
242  $orgu_ref_ids[] = $res['ref_id'];
243  }
244  $employees = array();
245  foreach($orgu_ref_ids as $orgu_ref_id){
246  $employees = array_merge($employees, $this->getEmployees($orgu_ref_id, $recursive));
247  }
248  return $employees;
249  }
250 
256  public function getSuperiorsOfUser($user_id, $recursive = true){
257  //querry for all orgu where user_id is superior.
258  $q = "SELECT orgu.obj_id, refr.ref_id FROM object_data orgu
259  INNER JOIN object_reference refr ON refr.obj_id = orgu.obj_id
260  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)
261  INNER JOIN rbac_ua rbac ON rbac.usr_id = ".$this->db->quote($user_id, "integer")." AND roles.obj_id = rbac.rol_id
262  WHERE orgu.type = 'orgu'";
263  $set = $this->db->query($q);
264  $orgu_ref_ids = array();
265  while($res = $this->db->fetchAssoc($set)){
266  $orgu_ref_ids[] = $res['ref_id'];
267  }
268  $superiors = array();
269  foreach($orgu_ref_ids as $orgu_ref_id){
270  $superiors = array_merge($superiors, $this->getSuperiors($orgu_ref_id, $recursive));
271  }
272  return $superiors;
273  }
274 
275 
284  public function getLevelXOfUser($user_id, $level) {
285  $q = "SELECT orgu.obj_id, refr.ref_id FROM object_data orgu
286  INNER JOIN object_reference refr ON refr.obj_id = orgu.obj_id
287  INNER JOIN object_data roles ON roles.title LIKE CONCAT('il_orgu_superior_',refr.ref_id) OR roles.title LIKE CONCAT('il_orgu_employee_',refr.ref_id)
288  INNER JOIN rbac_ua rbac ON rbac.usr_id = " . $this->db->quote($user_id, "integer") . " AND roles.obj_id = rbac.rol_id
289  WHERE orgu.type = 'orgu' AND refr.deleted IS NULL";
290  $set = $this->db->query($q);
291  $orgu_ref_ids = array();
292  while ($res = $this->db->fetchAssoc($set)) {
293  $orgu_ref_ids[] = $res['ref_id'];
294  }
295  $orgus_on_level_x = array();
296  foreach($orgu_ref_ids as $orgu_ref_id){
297  try{
298  $orgus_on_level_x[] = $this->getLevelXOfTreenode($orgu_ref_id, $level);
299  }catch(Exception $e){
300  // this means the user is assigned to a orgu above the given level. just dont add it to the list.
301  }
302  }
303 
304  return array_unique($orgus_on_level_x);
305  }
306 
307 
315  public function getOrgUnitOfUser($user_id, $ref_id = 0){
316  $q = "SELECT orgu.obj_id, refr.ref_id FROM object_data orgu
317  INNER JOIN object_reference refr ON refr.obj_id = orgu.obj_id
318  INNER JOIN object_data roles ON roles.title LIKE CONCAT('il_orgu_superior_',refr.ref_id) OR roles.title LIKE CONCAT('il_orgu_employee_',refr.ref_id)
319  INNER JOIN rbac_ua rbac ON rbac.usr_id = ".$this->db->quote($user_id, "integer")." AND roles.obj_id = rbac.rol_id
320  WHERE orgu.type = 'orgu' AND refr.deleted IS NULL";
321  $set = $this->db->query($q);
322  $orgu_ref_ids = array();
323  while($res = $this->db->fetchAssoc($set)){
324  $orgu_ref_ids[] = $res['ref_id'];
325  }
326  $orgu_ref_ids = array_unique($orgu_ref_ids);
327  if ($ref_id) {
328  $childernOrgIds = $this->getAllChildren($ref_id);
329  foreach ($orgu_ref_ids as $k => $refId) {
330  if (!in_array($refId, $childernOrgIds)) {
331  unset($orgu_ref_ids[$k]);
332  }
333  }
334  }
335  return $orgu_ref_ids;
336  }
337 
338  public function getTitles($org_refs){
339  $names = array();
340  foreach($org_refs as $org_unit){
341  $names[$org_unit] = ilObject::_lookupTitle(ilObject::_lookupObjId($org_unit));
342  }
343  return $names;
344  }
345 
349  public function getEmployeeRoles(){
350  $this->loadRoles("employee");
351  return $this->roles["employee"];
352  }
353 
354  public function getSuperiorRoles(){
355  $this->loadRoles("superior");
356  return $this->roles["superior"];
357  }
358 
359  private function loadRoles($role){
360  if($this->roles[$role] == null){
361  $this->loadRolesQuery($role);
362  }
363  }
364 
365  public function flushCache(){
366  $this->roles = null;
367  }
368 
369  private function loadRolesQuery($role){
370  $this->roles[$role] = array();
371  $q = "SELECT obj_id, title FROM object_data WHERE type = 'role' AND title LIKE 'il_orgu_".$role."%'";
372  $set = $this->db->query($q);
373  while($res = $this->db->fetchAssoc($set)){
374  $orgu_ref = $this->getRefIdFromRoleTitle($res["title"]);
375  $this->roles[$role][$orgu_ref] = $res["obj_id"];
376  $this->role_to_orgu[$role][$res["obj_id"]] = $orgu_ref;
377  }
378  }
379 
380  private function getRefIdFromRoleTitle($role_title){
381  $array = explode("_", $role_title);
382  return $array[count($array) - 1];
383  }
384 
402  public function getLevelXOfTreenode($orgu_ref, $level){
403  $line = array($orgu_ref);
404  $current_ref = $orgu_ref;
405  while($current_ref != ilObjOrgUnit::getRootOrgRefId()){
406  $current_ref = $this->getParent($current_ref);
407  if($current_ref)
408  $line[] = $current_ref;
409  else
410  break;
411  if(count($line) > 100)
412  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");
413  }
414  $line = array_reverse($line);
415  if(count($line) > $level)
416  return $line[$level];
417  else
418  throw new Exception("you want to fetch level ".$level." but the line to the length of the line is only ".count($line). ". The line of the given org unit is: ".print_r($line , true));
419  }
420 
421  public function getParent($orgu_ref){
422  if(!$this->parent[$orgu_ref]){
423  $this->parent[$orgu_ref] = $this->tree->getParentId($orgu_ref);
424  }
425  return $this->parent[$orgu_ref];
426  }
427 }
428 
429 ?>