ILIAS  Release_4_4_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.ilRbacReview.php
Go to the documentation of this file.
1 <?php
2 
3 /* Copyright (c) 1998-2010 ILIAS open source, Extended GPL, see docs/LICENSE */
4 
21 {
22  const FILTER_ALL = 1;
23  const FILTER_ALL_GLOBAL = 2;
24  const FILTER_ALL_LOCAL = 3;
25  const FILTER_INTERNAL = 4;
27  const FILTER_TEMPLATES = 6;
28 
29  protected $assigned_roles = array();
30  var $log = null;
31 
32  // Cache operation ids
33  private static $_opsCache = null;
34 
39  function ilRbacReview()
40  {
41  global $ilDB,$ilErr,$ilias,$ilLog;
42 
43  $this->log =& $ilLog;
44 
45  // set db & error handler
46  (isset($ilDB)) ? $this->ilDB =& $ilDB : $this->ilDB =& $ilias->db;
47 
48  if (!isset($ilErr))
49  {
50  $ilErr = new ilErrorHandling();
51  $ilErr->setErrorHandling(PEAR_ERROR_CALLBACK,array($ilErr,'errorHandler'));
52  }
53  else
54  {
55  $this->ilErr =& $ilErr;
56  }
57  }
58 
105  function searchRolesByMailboxAddressList($a_address_list)
106  {
107  global $ilDB;
108 
109  $role_ids = array();
110 
111  include_once "Services/Mail/classes/class.ilMail.php";
112  if(ilMail::_usePearMail())
113  {
114  require_once './Services/PEAR/lib/Mail/RFC822.php';
115  $parser = new Mail_RFC822();
116  $parsedList = $parser->parseAddressList($a_address_list, "ilias", false, true);
117  foreach ($parsedList as $address)
118  {
119  $local_part = $address->mailbox;
120  if (strpos($local_part,'#') !== 0 &&
121  !($local_part{0} == '"' && $local_part{1} == "#"))
122  {
123  // A local-part which doesn't start with a '#' doesn't denote a role.
124  // Therefore we can skip it.
125  continue;
126  }
127 
128  $local_part = substr($local_part, 1);
129 
130  /* If role contains spaces, eg. 'foo role', double quotes are added which have to be
131  removed here.*/
132  if( $local_part{0} == '#' && $local_part{strlen($local_part) - 1} == '"' )
133  {
134  $local_part = substr($local_part, 1);
135  $local_part = substr($local_part, 0, strlen($local_part) - 1);
136  }
137 
138  if (substr($local_part,0,8) == 'il_role_')
139  {
140  $role_id = substr($local_part,8);
141  $query = "SELECT t.tree ".
142  "FROM rbac_fa fa ".
143  "JOIN tree t ON t.child = fa.parent ".
144  "WHERE fa.rol_id = ".$this->ilDB->quote($role_id,'integer')." ".
145  "AND fa.assign = 'y' ".
146  "AND t.tree = 1";
147  $r = $ilDB->query($query);
148  if ($r->numRows() > 0)
149  {
150  $role_ids[] = $role_id;
151  }
152  continue;
153  }
154 
155 
156  $domain = $address->host;
157  if (strpos($domain,'[') == 0 && strrpos($domain,']'))
158  {
159  $domain = substr($domain,1,strlen($domain) - 2);
160  }
161  if (strlen($local_part) == 0)
162  {
163  $local_part = $domain;
164  $address->host = 'ilias';
165  $domain = 'ilias';
166  }
167 
168  if (strtolower($address->host) == 'ilias')
169  {
170  // Search for roles = local-part in the whole repository
171  $query = "SELECT dat.obj_id ".
172  "FROM object_data dat ".
173  "JOIN rbac_fa fa ON fa.rol_id = dat.obj_id ".
174  "JOIN tree t ON t.child = fa.parent ".
175  "WHERE dat.title =".$this->ilDB->quote($local_part,'text')." ".
176  "AND dat.type = 'role' ".
177  "AND fa.assign = 'y' ".
178  "AND t.tree = 1";
179  }
180  else
181  {
182  // Search for roles like local-part in objects = host
183  $query = "SELECT rdat.obj_id ".
184  "FROM object_data odat ".
185  "JOIN object_reference oref ON oref.obj_id = odat.obj_id ".
186  "JOIN tree otree ON otree.child = oref.ref_id ".
187  "JOIN tree rtree ON rtree.parent = otree.child ".
188  "JOIN rbac_fa rfa ON rfa.parent = rtree.child ".
189  "JOIN object_data rdat ON rdat.obj_id = rfa.rol_id ".
190  "WHERE odat.title = ".$this->ilDB->quote($domain,'text')." ".
191  "AND otree.tree = 1 AND rtree.tree = 1 ".
192  "AND rfa.assign = 'y' ".
193  "AND rdat.title LIKE ".
194  $this->ilDB->quote('%'.preg_replace('/([_%])/','\\\\$1',$local_part).'%','text');
195  }
196  $r = $ilDB->query($query);
197 
198  $count = 0;
199  while($row = $r->fetchRow(DB_FETCHMODE_OBJECT))
200  {
201  $role_ids[] = $row->obj_id;
202  $count++;
203  }
204 
205  // Nothing found?
206  // In this case, we search for roles = host.
207  if ($count == 0 && strtolower($address->host) == 'ilias')
208  {
209  $q = "SELECT dat.obj_id ".
210  "FROM object_data dat ".
211  "JOIN object_reference ref ON ref.obj_id = dat.obj_id ".
212  "JOIN tree t ON t.child = ref.ref_id ".
213  "WHERE dat.title = ".$this->ilDB->quote($domain ,'text')." ".
214  "AND dat.type = 'role' ".
215  "AND t.tree = 1 ";
216  $r = $this->ilDB->query($q);
217 
218  while($row = $r->fetchRow(DB_FETCHMODE_OBJECT))
219  {
220  $role_ids[] = $row->obj_id;
221  }
222  }
223  //echo '<br>ids='.var_export($role_ids,true);
224  }
225  }
226  else
227  {
228  // the following code is executed, when Pear Mail is
229  // not installed
230 
231  $titles = explode(',', $a_address_list);
232 
233  $titleList = '';
234  foreach ($titles as $title)
235  {
236  if (strlen($inList) > 0)
237  {
238  $titleList .= ',';
239  }
240  $title = trim($title);
241  if (strpos($title,'#') == 0)
242  {
243  $titleList .= $this->ilDB->quote(substr($title, 1));
244  }
245  }
246  if (strlen($titleList) > 0)
247  {
248  $q = "SELECT obj_id ".
249  "FROM object_data ".
250  "WHERE title IN (".$titleList.") ".
251  "AND type='role'";
252  $r = $this->ilDB->query($q);
253  while ($row = $r->fetchRow(DB_FETCHMODE_OBJECT))
254  {
255  $role_ids[] = $row->obj_id;
256  }
257  }
258  }
259 
260  return $role_ids;
261  }
262 
326  function getRoleMailboxAddress($a_role_id, $is_localize = true)
327  {
328  global $log, $lng,$ilDB;
329 
330  include_once "Services/Mail/classes/class.ilMail.php";
331  if (ilMail::_usePearMail())
332  {
333  // Retrieve the role title and the object title.
334  $query = "SELECT rdat.title role_title,odat.title object_title, ".
335  " oref.ref_id object_ref ".
336  "FROM object_data rdat ".
337  "JOIN rbac_fa fa ON fa.rol_id = rdat.obj_id ".
338  "JOIN tree rtree ON rtree.child = fa.parent ".
339  "JOIN object_reference oref ON oref.ref_id = rtree.parent ".
340  "JOIN object_data odat ON odat.obj_id = oref.obj_id ".
341  "WHERE rdat.obj_id = ".$this->ilDB->quote($a_role_id,'integer')." ".
342  "AND fa.assign = 'y' ";
343  $r = $ilDB->query($query);
344  if (!$row = $ilDB->fetchObject($r))
345  {
346  //$log->write('class.ilRbacReview->getMailboxAddress('.$a_role_id.'): error role does not exist');
347  return null; // role does not exist
348  }
349  $object_title = $row->object_title;
350  $object_ref = $row->object_ref;
351  $role_title = $row->role_title;
352 
353 
354  // In a perfect world, we could use the object_title in the
355  // domain part of the mailbox address, and the role title
356  // with prefix '#' in the local part of the mailbox address.
357  $domain = $object_title;
358  $local_part = $role_title;
359 
360 
361  // Determine if the object title is unique
362  $q = "SELECT COUNT(DISTINCT dat.obj_id) count ".
363  "FROM object_data dat ".
364  "JOIN object_reference ref ON ref.obj_id = dat.obj_id ".
365  "JOIN tree ON tree.child = ref.ref_id ".
366  "WHERE title = ".$this->ilDB->quote($object_title,'text')." ".
367  "AND tree.tree = 1 ";
368  $r = $this->ilDB->query($q);
369  $row = $r->fetchRow(DB_FETCHMODE_OBJECT);
370 
371  // If the object title is not unique, we get rid of the domain.
372  if ($row->count > 1)
373  {
374  $domain = null;
375  }
376 
377  // If the domain contains illegal characters, we get rid of it.
378  //if (domain != null && preg_match('/[\[\]\\]|[\x00-\x1f]/',$domain))
379  // Fix for Mantis Bug: 7429 sending mail fails because of brakets
380  // Fix for Mantis Bug: 9978 sending mail fails because of semicolon
381  if ($domain != null && preg_match('/[\[\]\\]|[\x00-\x1f]|[\x28-\x29]|[;]/',$domain))
382  {
383  $domain = null;
384  }
385 
386  // If the domain contains special characters, we put square
387  // brackets around it.
388  if ($domain != null &&
389  (preg_match('/[()<>@,;:\\".\[\]]/',$domain) ||
390  preg_match('/[^\x21-\x8f]/',$domain))
391  )
392  {
393  $domain = '['.$domain.']';
394  }
395 
396  // If the role title is one of the ILIAS reserved role titles,
397  // we can use a shorthand version of it for the local part
398  // of the mailbox address.
399  if (strpos($role_title, 'il_') === 0 && $domain != null)
400  {
401  $unambiguous_role_title = $role_title;
402 
403  $pos = strpos($role_title, '_', 3) + 1;
404  $local_part = substr(
405  $role_title,
406  $pos,
407  strrpos($role_title, '_') - $pos
408  );
409  }
410  else
411  {
412  $unambiguous_role_title = 'il_role_'.$a_role_id;
413  }
414 
415  // Determine if the local part is unique. If we don't have a
416  // domain, the local part must be unique within the whole repositry.
417  // If we do have a domain, the local part must be unique for that
418  // domain.
419  if ($domain == null)
420  {
421  $q = "SELECT COUNT(DISTINCT dat.obj_id) count ".
422  "FROM object_data dat ".
423  "JOIN object_reference ref ON ref.obj_id = dat.obj_id ".
424  "JOIN tree ON tree.child = ref.ref_id ".
425  "WHERE title = ".$this->ilDB->quote($local_part,'text')." ".
426  "AND tree.tree = 1 ";
427  }
428  else
429  {
430  $q = "SELECT COUNT(rd.obj_id) count ".
431  "FROM object_data rd ".
432  "JOIN rbac_fa fa ON rd.obj_id = fa.rol_id ".
433  "JOIN tree t ON t.child = fa.parent ".
434  "WHERE fa.assign = 'y' ".
435  "AND t.parent = ".$this->ilDB->quote($object_ref,'integer')." ".
436  "AND rd.title LIKE ".$this->ilDB->quote(
437  '%'.preg_replace('/([_%])/','\\\\$1', $local_part).'%','text')." ";
438  }
439 
440  $r = $this->ilDB->query($q);
441  $row = $r->fetchRow(DB_FETCHMODE_OBJECT);
442 
443  // if the local_part is not unique, we use the unambiguous role title
444  // instead for the local part of the mailbox address
445  if ($row->count > 1)
446  {
447  $local_part = $unambiguous_role_title;
448  }
449 
450  $use_phrase = true;
451 
452  // If the local part contains illegal characters, we use
453  // the unambiguous role title instead.
454  if (preg_match('/[\\"\x00-\x1f]/',$local_part))
455  {
456  $local_part = $unambiguous_role_title;
457  }
458  else if(!preg_match('/^[\\x00-\\x7E]+$/i', $local_part))
459  {
460  // 2013-12-05: According to #12283, we do not accept umlauts in the local part
461  $local_part = $unambiguous_role_title;
462  $use_phrase = false;
463  }
464 
465  // Add a "#" prefix to the local part
466  $local_part = '#'.$local_part;
467 
468  // Put quotes around the role title, if needed
469  if (preg_match('/[()<>@,;:.\[\]\x20]/',$local_part))
470  {
471  $local_part = '"'.$local_part.'"';
472  }
473 
474  $mailbox = ($domain == null) ?
475  $local_part :
476  $local_part.'@'.$domain;
477 
478  if ($is_localize)
479  {
480  if (substr($role_title,0,3) == 'il_')
481  {
482  $phrase = $lng->txt(substr($role_title, 0, strrpos($role_title,'_')));
483  }
484  else
485  {
486  $phrase = $role_title;
487  }
488 
489  if($use_phrase)
490  {
491  // make phrase RFC 822 conformant:
492  // - strip excessive whitespace
493  // - strip special characters
494  $phrase = preg_replace('/\s\s+/', ' ', $phrase);
495  $phrase = preg_replace('/[()<>@,;:\\".\[\]]/', '', $phrase);
496 
497  $mailbox = $phrase.' <'.$mailbox.'>';
498  }
499  }
500 
501  require_once './Services/PEAR/lib/Mail/RFC822.php';
502  $obj = new Mail_RFC822($mailbox, 'ilias');
503  if(@$obj->parseAddressList() instanceof PEAR_Error)
504  {
505  $q = "SELECT title ".
506  "FROM object_data ".
507  "WHERE obj_id = ".$this->ilDB->quote($a_role_id ,'integer');
508  $r = $this->ilDB->query($q);
509 
510  if ($row = $r->fetchRow(DB_FETCHMODE_OBJECT))
511  {
512  return '#'.$row->title;
513  }
514  else
515  {
516  return null;
517  }
518  }
519 
520  return $mailbox;
521  }
522  else
523  {
524  $q = "SELECT title ".
525  "FROM object_data ".
526  "WHERE obj_id = ".$this->ilDB->quote($a_role_id ,'integer');
527  $r = $this->ilDB->query($q);
528 
529  if ($row = $r->fetchRow(DB_FETCHMODE_OBJECT))
530  {
531  return '#'.$row->title;
532  }
533  else
534  {
535  return null;
536  }
537  }
538  }
539 
540 
548  function roleExists($a_title,$a_id = 0)
549  {
550  global $ilDB;
551 
552  if (empty($a_title))
553  {
554  $message = get_class($this)."::roleExists(): No title given!";
555  $this->ilErr->raiseError($message,$this->ilErr->WARNING);
556  }
557 
558  $clause = ($a_id) ? " AND obj_id != ".$ilDB->quote($a_id)." " : "";
559 
560  $q = "SELECT DISTINCT(obj_id) obj_id FROM object_data ".
561  "WHERE title =".$ilDB->quote($a_title)." ".
562  "AND type IN('role','rolt')".
563  $clause." ";
564  $r = $this->ilDB->query($q);
565 
566  while($row = $r->fetchRow(DB_FETCHMODE_OBJECT))
567  {
568  return $row->obj_id;
569  }
570  return false;
571  }
572 
585  function __getParentRoles($a_path,$a_templates,$a_keep_protected)
586  {
587  global $log,$ilDB;
588 
589  if (!isset($a_path) or !is_array($a_path))
590  {
591  $message = get_class($this)."::getParentRoles(): No path given or wrong datatype!";
592  $this->ilErr->raiseError($message,$this->ilErr->WARNING);
593  }
594 
595  $parent_roles = array();
596  $role_hierarchy = array();
597 
598  // Select all role folders on a path using a single SQL-statement.
599  // CREATE IN() STATEMENT
600  $in = $ilDB->in('t.parent',$a_path,false,'integer');
601 
602  $q = "SELECT t.child,t.depth FROM tree t ".
603  "JOIN object_reference r ON r.ref_id = t.child ".
604  "JOIN object_data o ON o.obj_id = r.obj_id ".
605  "WHERE ".$in." ".
606  "AND o.type= ".$ilDB->quote('rolf','text')." ".
607  "ORDER BY t.depth ASC";
608 
609  $r = $this->ilDB->query($q);
610 
611 
612  // Sort by path (Administration -> Rolefolder is first element)
613  $role_rows = array();
614  while($row = $r->fetchRow(DB_FETCHMODE_OBJECT))
615  {
616 
617  $depth = ($row->child == ROLE_FOLDER_ID ? 0 : $row->depth);
618  $role_rows[$depth]['child'] = $row->child;
619  }
620  ksort($role_rows,SORT_NUMERIC);
621 
622  foreach($role_rows as $row)
623  {
624  $roles = $this->getRoleListByObject($row['child'],$a_templates);
625  foreach ($roles as $role)
626  {
627  $id = $role["obj_id"];
628  $role["parent"] = $row['child'];
629  $parent_roles[$id] = $role;
630 
631  if (!array_key_exists($role['obj_id'],$role_hierarchy))
632  {
633  $role_hierarchy[$id] = $row['child'];
634  }
635  }
636  }
637  if (!$a_keep_protected)
638  {
639  return $this->__setProtectedStatus($parent_roles,$role_hierarchy,reset($a_path));
640  }
641  return $parent_roles;
642  }
643 
652  function getParentRoleIds($a_endnode_id,$a_templates = false,$a_keep_protected = false)
653  {
654  global $tree,$log,$ilDB;
655 
656  if (!isset($a_endnode_id))
657  {
658  $GLOBALS['ilLog']->logStack();
659  $message = get_class($this)."::getParentRoleIds(): No node_id (ref_id) given!";
660  $this->ilErr->raiseError($message,$this->ilErr->WARNING);
661  }
662 
663  //var_dump($a_endnode_id);exit;
664  //$log->write("ilRBACreview::getParentRoleIds(), 0");
665  $pathIds = $tree->getPathId($a_endnode_id);
666 
667  // add system folder since it may not in the path
668  $pathIds[0] = SYSTEM_FOLDER_ID;
669  //$log->write("ilRBACreview::getParentRoleIds(), 1");
670  #return $this->getParentRoles($a_endnode_id,$a_templates,$a_keep_protected);
671  return $this->__getParentRoles($pathIds,$a_templates,$a_keep_protected);
672  }
673 
681  function getRoleListByObject($a_ref_id,$a_templates = false)
682  {
683  global $ilDB;
684 
685  if (!isset($a_ref_id) or !isset($a_templates))
686  {
687  $message = get_class($this)."::getRoleListByObject(): Missing parameter!".
688  "ref_id: ".$a_ref_id.
689  "tpl_flag: ".$a_templates;
690  $this->ilErr->raiseError($message,$this->ilErr->WARNING);
691  }
692 
693  $role_list = array();
694 
695  $where = $this->__setTemplateFilter($a_templates);
696 
697  $query = "SELECT * FROM object_data ".
698  "JOIN rbac_fa ON obj_id = rol_id ".
699  $where.
700  "AND object_data.obj_id = rbac_fa.rol_id ".
701  "AND rbac_fa.parent = ".$ilDB->quote($a_ref_id,'integer')." ";
702 
703  $res = $ilDB->query($query);
704  while ($row = $ilDB->fetchAssoc($res))
705  {
706  $row["desc"] = $row["description"];
707  $row["user_id"] = $row["owner"];
708  $role_list[] = $row;
709  }
710 
711  $role_list = $this->__setRoleType($role_list);
712 
713  return $role_list;
714  }
715 
722  function getAssignableRoles($a_templates = false,$a_internal_roles = false, $title_filter = '')
723  {
724  global $ilDB;
725 
726  $role_list = array();
727 
728  $where = $this->__setTemplateFilter($a_templates);
729 
730  $query = "SELECT * FROM object_data ".
731  "JOIN rbac_fa ON obj_id = rol_id ".
732  $where.
733  "AND rbac_fa.assign = 'y' ";
734 
735  if(strlen($title_filter))
736  {
737  $query .= (' AND '.$ilDB->like(
738  'title',
739  'text',
740  $title_filter.'%'
741  ));
742  }
743  $res = $ilDB->query($query);
744 
745  while ($row = $ilDB->fetchAssoc($res))
746  {
747  $row["desc"] = $row["description"];
748  $row["user_id"] = $row["owner"];
749  $role_list[] = $row;
750  }
751 
752  $role_list = $this->__setRoleType($role_list);
753 
754  return $role_list;
755  }
756 
764  {
765  global $ilDB;
766 
767 
768  $query = 'SELECT rol_id FROM rbac_fa fa '.
769  'JOIN tree t1 ON t1.child = fa.parent '.
770  'JOIN object_data obd ON fa.rol_id = obd.obj_id ' .
771  'WHERE assign = '.$ilDB->quote('y','text').' '.
772  'AND obd.type = '.$ilDB->quote('role','text').' '.
773  'AND t1.parent IN ('.
774  $GLOBALS['tree']->getSubTreeQuery($ref_id,array('child')).' '.
775  ') ';
776 
777 
778  $res = $ilDB->query($query);
779 
780  $role_list = array();
781  while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
782  {
783  $role_list[] = $row->rol_id;
784  }
785  return $role_list;
786  }
787 
794  function getAssignableChildRoles($a_ref_id)
795  {
796  global $ilDB;
797  global $tree;
798 
799  $query = "SELECT fa.*, rd.* ".
800  "FROM object_data rd ".
801  "JOIN rbac_fa fa ON rd.obj_id = fa.rol_id ".
802  "JOIN tree t ON t.child = fa.parent ".
803  "WHERE fa.assign = 'y' ".
804  "AND t.parent = ".$this->ilDB->quote($a_ref_id,'integer')." "
805  ;
806  $res = $ilDB->query($query);
807  while($row = $ilDB->fetchAssoc($res))
808  {
809  $roles_data[] = $row;
810  }
811  return $roles_data ? $roles_data : array();
812  }
813 
820  function __setTemplateFilter($a_templates)
821  {
822  global $ilDB;
823 
824  if ($a_templates === true)
825  {
826  $where = "WHERE ".$ilDB->in('object_data.type',array('role','rolt'),false,'text')." ";
827  }
828  else
829  {
830  $where = "WHERE ".$ilDB->in('object_data.type',array('role'),false,'text')." ";
831  }
832 
833  return $where;
834  }
835 
847  function __setRoleType($a_role_list)
848  {
849  foreach ($a_role_list as $key => $val)
850  {
851  // determine role type
852  if ($val["type"] == "rolt")
853  {
854  $a_role_list[$key]["role_type"] = "template";
855  }
856  else
857  {
858  if ($val["assign"] == "y")
859  {
860  if ($val["parent"] == ROLE_FOLDER_ID)
861  {
862  $a_role_list[$key]["role_type"] = "global";
863  }
864  else
865  {
866  $a_role_list[$key]["role_type"] = "local";
867  }
868  }
869  else
870  {
871  $a_role_list[$key]["role_type"] = "linked";
872  }
873  }
874 
875  if ($val["protected"] == "y")
876  {
877  $a_role_list[$key]["protected"] = true;
878  }
879  else
880  {
881  $a_role_list[$key]["protected"] = false;
882  }
883  }
884 
885  return $a_role_list;
886  }
887 
894  public function getNumberOfAssignedUsers(Array $a_roles)
895  {
896  global $ilDB;
897 
898  $query = 'SELECT COUNT(DISTINCT(usr_id)) as num FROM rbac_ua '.
899  'WHERE '.$ilDB->in('rol_id', $a_roles, false, 'integer').' ';
900 
901  $res = $ilDB->query($query);
902  $row = $res->fetchRow(DB_FETCHMODE_OBJECT);
903  return $row->num ? $row->num : 0;
904  }
905 
913  function assignedUsers($a_rol_id, $a_fields = NULL)
914  {
915  global $ilBench,$ilDB;
916 
917  $ilBench->start("RBAC", "review_assignedUsers");
918 
919  if (!isset($a_rol_id))
920  {
921  $message = get_class($this)."::assignedUsers(): No role_id given!";
922  $this->ilErr->raiseError($message,$this->ilErr->WARNING);
923  }
924 
925  $result_arr = array();
926 
927  if ($a_fields !== NULL and is_array($a_fields))
928  {
929  if (count($a_fields) == 0)
930  {
931  $select = "*";
932  }
933  else
934  {
935  if (($usr_id_field = array_search("usr_id",$a_fields)) !== false)
936  unset($a_fields[$usr_id_field]);
937 
938  $select = implode(",",$a_fields).",usr_data.usr_id";
939  $select = addslashes($select);
940  }
941 
942  $ilDB->enableResultBuffering(false);
943  $query = "SELECT ".$select." FROM usr_data ".
944  "LEFT JOIN rbac_ua ON usr_data.usr_id = rbac_ua.usr_id ".
945  "WHERE rbac_ua.rol_id =".$ilDB->quote($a_rol_id,'integer');
946  $res = $ilDB->query($query);
947  while($row = $ilDB->fetchAssoc($res))
948  {
949  $result_arr[] = $row;
950  }
951  $ilDB->enableResultBuffering(true);
952  }
953  else
954  {
955  $ilDB->enableResultBuffering(false);
956  $query = "SELECT usr_id FROM rbac_ua WHERE rol_id= ".$ilDB->quote($a_rol_id,'integer');
957 
958  $res = $ilDB->query($query);
959  while($row = $ilDB->fetchAssoc($res))
960  {
961  array_push($result_arr,$row["usr_id"]);
962  }
963  $ilDB->enableResultBuffering(true);
964  }
965 
966  $ilBench->stop("RBAC", "review_assignedUsers");
967 
968  return $result_arr;
969  }
970 
978  function isAssigned($a_usr_id,$a_role_id)
979  {
980  // Quickly determine if user is assigned to a role
981  global $ilDB;
982 
983  $ilDB->setLimit(1,0);
984  $query = "SELECT usr_id FROM rbac_ua WHERE ".
985  "rol_id= ".$ilDB->quote($a_role_id,'integer')." ".
986  "AND usr_id= ".$ilDB->quote($a_usr_id);
987  $res = $ilDB->query($query);
988 
989  return $res->numRows() == 1;
990  }
991 
1003  function isAssignedToAtLeastOneGivenRole($a_usr_id,$a_role_ids)
1004  {
1005  global $ilDB;
1006 
1007  $ilDB->setLimit(1,0);
1008  $query = "SELECT usr_id FROM rbac_ua WHERE ".
1009  $ilDB->in('rol_id',$a_role_ids,false,'integer').
1010  " AND usr_id= ".$ilDB->quote($a_usr_id);
1011  $res = $ilDB->query($query);
1012 
1013  return $ilDB->numRows($res) == 1;
1014  }
1015 
1022  function assignedRoles($a_usr_id)
1023  {
1024  global $ilDB;
1025 
1026  $role_arr = array();
1027 
1028  $query = "SELECT rol_id FROM rbac_ua WHERE usr_id = ".$ilDB->quote($a_usr_id,'integer');
1029 
1030  $res = $ilDB->query($query);
1031  while($row = $ilDB->fetchObject($res))
1032  {
1033  $role_arr[] = $row->rol_id;
1034  }
1035  return $role_arr ? $role_arr : array();
1036  }
1037 
1042  public function assignedGlobalRoles($a_usr_id)
1043  {
1044  global $ilDB;
1045 
1046  $query = "SELECT ua.rol_id FROM rbac_ua ua ".
1047  "JOIN rbac_fa fa ON ua.rol_id = fa.rol_id ".
1048  "WHERE usr_id = ".$ilDB->quote($a_usr_id,'integer').' '.
1049  "AND parent = ".$ilDB->quote(ROLE_FOLDER_ID)." ".
1050  "AND assign = 'y' ";
1051 
1052  $res = $ilDB->query($query);
1053  while($row = $ilDB->fetchObject($res))
1054  {
1055  $role_arr[] = $row->rol_id;
1056  }
1057  return $role_arr ? $role_arr : array();
1058  }
1059 
1067  function isAssignable($a_rol_id, $a_ref_id)
1068  {
1069  global $ilBench,$ilDB;
1070 
1071  $ilBench->start("RBAC", "review_isAssignable");
1072 
1073  // exclude system role from rbac
1074  if ($a_rol_id == SYSTEM_ROLE_ID)
1075  {
1076  $ilBench->stop("RBAC", "review_isAssignable");
1077  return true;
1078  }
1079 
1080  if (!isset($a_rol_id) or !isset($a_ref_id))
1081  {
1082  $message = get_class($this)."::isAssignable(): Missing parameter!".
1083  " role_id: ".$a_rol_id." ,ref_id: ".$a_ref_id;
1084  $this->ilErr->raiseError($message,$this->ilErr->WARNING);
1085  }
1086  $query = "SELECT * FROM rbac_fa ".
1087  "WHERE rol_id = ".$ilDB->quote($a_rol_id,'integer')." ".
1088  "AND parent = ".$ilDB->quote($a_ref_id,'integer')." ";
1089  $res = $ilDB->query($query);
1090  $row = $ilDB->fetchObject($res);
1091 
1092  $ilBench->stop("RBAC", "review_isAssignable");
1093  return $row->assign == 'y' ? true : false;
1094  }
1095 
1099  public function hasMultipleAssignments($a_role_id)
1100  {
1101  global $ilDB;
1102 
1103  $query = "SELECT * FROM rbac_fa WHERE rol_id = ".$ilDB->quote($a_role_id,'integer').' '.
1104  "AND assign = ".$ilDB->quote('y','text');
1105  $res = $ilDB->query($query);
1106  return $res->numRows() > 1;
1107  }
1108 
1119  function getFoldersAssignedToRole($a_rol_id, $a_assignable = false)
1120  {
1121  global $ilDB;
1122 
1123  if (!isset($a_rol_id))
1124  {
1125  $message = get_class($this)."::getFoldersAssignedToRole(): No role_id given!";
1126  $this->ilErr->raiseError($message,$this->ilErr->WARNING);
1127  }
1128 
1129  if ($a_assignable)
1130  {
1131  $where = " AND assign ='y'";
1132  }
1133 
1134  $query = "SELECT DISTINCT parent FROM rbac_fa ".
1135  "WHERE rol_id = ".$ilDB->quote($a_rol_id,'integer')." ".$where." ";
1136 
1137  $res = $ilDB->query($query);
1138  while($row = $ilDB->fetchObject($res))
1139  {
1140  $folders[] = $row->parent;
1141  }
1142  return $folders ? $folders : array();
1143  }
1144 
1153  function getRolesOfRoleFolder($a_ref_id,$a_nonassignable = true)
1154  {
1155  global $ilBench,$ilDB,$ilLog;
1156 
1157  $ilBench->start("RBAC", "review_getRolesOfRoleFolder");
1158 
1159  if (!isset($a_ref_id))
1160  {
1161  $message = get_class($this)."::getRolesOfRoleFolder(): No ref_id given!";
1162  $this->ilErr->raiseError($message,$this->ilErr->WARNING);
1163 
1164  }
1165 
1166  if ($a_nonassignable === false)
1167  {
1168  $and = " AND assign='y'";
1169  }
1170 
1171  $query = "SELECT rol_id FROM rbac_fa ".
1172  "WHERE parent = ".$ilDB->quote($a_ref_id,'integer')." ".
1173  $and;
1174 
1175  $res = $ilDB->query($query);
1176  while($row = $ilDB->fetchObject($res))
1177  {
1178  $rol_id[] = $row->rol_id;
1179  }
1180 
1181  $ilBench->stop("RBAC", "review_getRolesOfRoleFolder");
1182 
1183  return $rol_id ? $rol_id : array();
1184  }
1185 
1191  function getGlobalRoles()
1192  {
1193  return $this->getRolesOfRoleFolder(ROLE_FOLDER_ID,false);
1194  }
1195 
1200  public function getLocalRoles($a_ref_id)
1201  {
1202  global $ilDB;
1203 
1204  // @todo: all this in one query
1205  $rolf = $this->getRoleFolderIdOfObject($a_ref_id);
1206  if(!$rolf)
1207  {
1208  return array();
1209  }
1210  $lroles = array();
1211  foreach($this->getRolesOfRoleFolder($rolf) as $role_id)
1212  {
1213  if($this->isAssignable($role_id, $rolf))
1214  {
1215  $lroles[] = $role_id;
1216  }
1217  }
1218  return $lroles;
1219  }
1220 
1227  {
1228  foreach($this->getRolesOfRoleFolder(ROLE_FOLDER_ID,false) as $role_id)
1229  {
1230  $ga[] = array('obj_id' => $role_id,
1231  'role_type' => 'global');
1232  }
1233  return $ga ? $ga : array();
1234  }
1235 
1242  {
1243  include_once './Services/AccessControl/classes/class.ilObjRole.php';
1244 
1245  foreach($this->getGlobalRoles() as $role_id)
1246  {
1247  if(ilObjRole::_getAssignUsersStatus($role_id))
1248  {
1249  $ga[] = array('obj_id' => $role_id,
1250  'role_type' => 'global');
1251  }
1252  }
1253  return $ga ? $ga : array();
1254  }
1255 
1262  {
1263  global $ilDB;
1264 
1265  $query = "SELECT DISTINCT parent FROM rbac_fa";
1266  $res = $ilDB->query($query);
1267 
1268  $parent = array();
1269  while($row = $ilDB->fetchObject($res))
1270  {
1271  $parent[] = $row->parent;
1272  }
1273  return $parent;
1274  }
1275 
1282  function getRoleFolderOfObject($a_ref_id)
1283  {
1284  global $tree,$ilBench;
1285 
1286  $ilBench->start("RBAC", "review_getRoleFolderOfObject");
1287 
1288  if (!isset($a_ref_id))
1289  {
1290  $GLOBALS['ilLog']->logStack();
1291  $message = get_class($this)."::getRoleFolderOfObject(): No ref_id given!";
1292  $this->ilErr->raiseError($message,$this->ilErr->WARNING);
1293  }
1294  $childs = $tree->getChildsByType($a_ref_id,"rolf");
1295 
1296  $ilBench->stop("RBAC", "review_getRoleFolderOfObject");
1297 
1298  return $childs[0] ? $childs[0] : array();
1299  }
1300 
1301  function getRoleFolderIdOfObject($a_ref_id)
1302  {
1303  $rolf = $this->getRoleFolderOfObject($a_ref_id);
1304 
1305  if (!$rolf)
1306  {
1307  return false;
1308  }
1309 
1310  return $rolf['ref_id'];
1311  }
1312 
1316  public function isRoleAssignedToFolder($a_role_id, $a_parent_id)
1317  {
1318  global $rbacreview, $ilDB;
1319 
1320  $query = 'SELECT * FROM rbac_fa '.
1321  'WHERE rol_id = '.$ilDB->quote($a_role_id,'integer').' '.
1322  'AND parent = '.$ilDB->quote($a_parent_id,'integer');
1323  $res = $ilDB->query($query);
1324  return $res->numRows() ? true : false;
1325  }
1326 
1332  function getOperations()
1333  {
1334  global $ilDB;
1335 
1336  $query = 'SELECT * FROM rbac_operations ORDER BY ops_id ';
1337  $res = $this->ilDB->query($query);
1338  while($row = $ilDB->fetchObject($res))
1339  {
1340  $ops[] = array('ops_id' => $row->ops_id,
1341  'operation' => $row->operation,
1342  'description' => $row->description);
1343  }
1344 
1345  return $ops ? $ops : array();
1346  }
1347 
1353  function getOperation($ops_id)
1354  {
1355  global $ilDB;
1356 
1357  $query = 'SELECT * FROM rbac_operations WHERE ops_id = '.$ilDB->quote($ops_id,'integer');
1358  $res = $this->ilDB->query($query);
1359  while($row = $ilDB->fetchObject($res))
1360  {
1361  $ops = array('ops_id' => $row->ops_id,
1362  'operation' => $row->operation,
1363  'description' => $row->description);
1364  }
1365 
1366  return $ops ? $ops : array();
1367  }
1368 
1377  public function getAllOperationsOfRole($a_rol_id, $a_parent = 0)
1378  {
1379  global $ilDB;
1380 
1381  if(!$a_parent)
1382  {
1383  $a_parent = ROLE_FOLDER_ID;
1384  }
1385 
1386  $query = "SELECT ops_id,type FROM rbac_templates ".
1387  "WHERE rol_id = ".$ilDB->quote($a_rol_id,'integer')." ".
1388  "AND parent = ".$ilDB->quote($a_parent,'integer');
1389  $res = $ilDB->query($query);
1390 
1391  while ($row = $ilDB->fetchObject($res))
1392  {
1393  $ops_arr[$row->type][] = $row->ops_id;
1394  }
1395  return (array) $ops_arr;
1396  }
1397 
1404  public function getActiveOperationsOfRole($a_ref_id, $a_role_id)
1405  {
1406  global $ilDB;
1407 
1408  $query = 'SELECT * FROM rbac_pa '.
1409  'WHERE ref_id = '.$ilDB->quote($a_ref_id,'integer').' '.
1410  'AND rol_id = '.$ilDB->quote($a_role_id,'integer').' ';
1411 
1412  $res = $ilDB->query($query);
1413  while($row = $res->fetchRow(DB_FETCHMODE_ASSOC))
1414  {
1415  return unserialize($row['ops_id']);
1416  }
1417  return array();
1418  }
1419 
1420 
1430  function getOperationsOfRole($a_rol_id,$a_type,$a_parent = 0)
1431  {
1432  global $ilDB,$ilLog;
1433 
1434  if (!isset($a_rol_id) or !isset($a_type))
1435  {
1436  $message = get_class($this)."::getOperationsOfRole(): Missing Parameter!".
1437  "role_id: ".$a_rol_id.
1438  "type: ".$a_type.
1439  "parent_id: ".$a_parent;
1440  $ilLog->logStack("Missing parameter! ");
1441  $this->ilErr->raiseError($message,$this->ilErr->WARNING);
1442  }
1443 
1444  $ops_arr = array();
1445 
1446  // if no rolefolder id is given, assume global role folder as target
1447  if ($a_parent == 0)
1448  {
1449  $a_parent = ROLE_FOLDER_ID;
1450  }
1451 
1452  $query = "SELECT ops_id FROM rbac_templates ".
1453  "WHERE type =".$ilDB->quote($a_type,'text')." ".
1454  "AND rol_id = ".$ilDB->quote($a_rol_id,'integer')." ".
1455  "AND parent = ".$ilDB->quote($a_parent,'integer');
1456  $res = $ilDB->query($query);
1457  while ($row = $ilDB->fetchObject($res))
1458  {
1459  $ops_arr[] = $row->ops_id;
1460  }
1461 
1462  return $ops_arr;
1463  }
1464 
1465  function getRoleOperationsOnObject($a_role_id,$a_ref_id)
1466  {
1467  global $ilDB;
1468 
1469  $query = "SELECT * FROM rbac_pa ".
1470  "WHERE rol_id = ".$ilDB->quote($a_role_id,'integer')." ".
1471  "AND ref_id = ".$ilDB->quote($a_ref_id,'integer')." ";
1472 
1473  $res = $ilDB->query($query);
1474  while($row = $ilDB->fetchObject($res))
1475  {
1476  $ops = unserialize($row->ops_id);
1477  }
1478 
1479  return $ops ? $ops : array();
1480  }
1481 
1488  function getOperationsOnType($a_typ_id)
1489  {
1490  global $ilDB;
1491 
1492  if (!isset($a_typ_id))
1493  {
1494  $message = get_class($this)."::getOperationsOnType(): No type_id given!";
1495  $this->ilErr->raiseError($message,$this->ilErr->WARNING);
1496  }
1497 
1498  #$query = "SELECT * FROM rbac_ta WHERE typ_id = ".$ilDB->quote($a_typ_id,'integer');
1499 
1500  $query = 'SELECT * FROM rbac_ta ta JOIN rbac_operations o ON ta.ops_id = o.ops_id '.
1501  'WHERE typ_id = '.$ilDB->quote($a_typ_id,'integer').' '.
1502  'ORDER BY op_order';
1503 
1504  $res = $ilDB->query($query);
1505 
1506  while($row = $ilDB->fetchObject($res))
1507  {
1508  $ops_id[] = $row->ops_id;
1509  }
1510 
1511  return $ops_id ? $ops_id : array();
1512  }
1513 
1520  function getOperationsOnTypeString($a_type)
1521  {
1522  global $ilDB;
1523 
1524  $query = "SELECT * FROM object_data WHERE type = 'typ' AND title = ".$ilDB->quote($a_type ,'text')." ";
1525 
1526 
1527  $res = $this->ilDB->query($query);
1528  while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
1529  {
1530  return $this->getOperationsOnType($row->obj_id);
1531  }
1532  return false;
1533  }
1534 
1541  public function getOperationsByTypeAndClass($a_type,$a_class)
1542  {
1543  global $ilDB;
1544 
1545  if($a_class != 'create')
1546  {
1547  $condition = "AND class != ".$ilDB->quote('create','text');
1548  }
1549  else
1550  {
1551  $condition = "AND class = ".$ilDB->quote('create','text');
1552  }
1553 
1554  $query = "SELECT ro.ops_id FROM rbac_operations ro ".
1555  "JOIN rbac_ta rt ON ro.ops_id = rt.ops_id ".
1556  "JOIN object_data od ON rt.typ_id = od.obj_id ".
1557  "WHERE type = ".$ilDB->quote('typ','text')." ".
1558  "AND title = ".$ilDB->quote($a_type,'text')." ".
1559  $condition." ".
1560  "ORDER BY op_order ";
1561 
1562  $res = $ilDB->query($query);
1563 
1564  $ops = array();
1565  while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
1566  {
1567  $ops[] = $row->ops_id;
1568  }
1569  return $ops;
1570  }
1571 
1572 
1581  function getObjectsWithStopedInheritance($a_rol_id,$a_filter = array())
1582  {
1583  global $ilDB;
1584 
1585  $query = 'SELECT t.parent p FROM tree t JOIN rbac_fa fa ON fa.parent = child '.
1586  'WHERE assign = '.$ilDB->quote('n','text').' '.
1587  'AND rol_id = '.$ilDB->quote($a_rol_id,'integer').' ';
1588 
1589  if($a_filter)
1590  {
1591  $query .= ('AND '.$ilDB->in('t.parent',(array) $a_filter,false,'integer'));
1592  }
1593 
1594  $res = $ilDB->query($query);
1595  $parent = array();
1596  while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
1597  {
1598  $parent[] = $row->p;
1599  }
1600  return $parent;
1601  }
1602 
1609  function isDeleted($a_node_id)
1610  {
1611  global $ilDB;
1612 
1613  $q = "SELECT tree FROM tree WHERE child =".$ilDB->quote($a_node_id)." ";
1614  $r = $this->ilDB->query($q);
1615 
1616  $row = $r->fetchRow(DB_FETCHMODE_OBJECT);
1617 
1618  if (!$row)
1619  {
1620  $message = sprintf('%s::isDeleted(): Role folder with ref_id %s not found!',
1621  get_class($this),
1622  $a_node_id);
1623  $this->log->write($message,$this->log->FATAL);
1624 
1625  return true;
1626  }
1627 
1628  // rolefolder is deleted
1629  if ($row->tree < 0)
1630  {
1631  return true;
1632  }
1633 
1634  return false;
1635  }
1636 
1642  public function isGlobalRole($a_role_id)
1643  {
1644  return in_array($a_role_id,$this->getGlobalRoles());
1645  }
1646 
1647  function getRolesByFilter($a_filter = 0,$a_user_id = 0, $title_filter = '')
1648  {
1649  global $ilDB;
1650 
1651  $assign = "y";
1652 
1653  switch($a_filter)
1654  {
1655  // all (assignable) roles
1656  case self::FILTER_ALL:
1657  return $this->getAssignableRoles(true,true,$title_filter);
1658  break;
1659 
1660  // all (assignable) global roles
1661  case self::FILTER_ALL_GLOBAL:
1662  $where = 'WHERE '.$ilDB->in('rbac_fa.rol_id',$this->getGlobalRoles(),false,'integer').' ';
1663  break;
1664 
1665  // all (assignable) local roles
1666  case self::FILTER_ALL_LOCAL:
1667  case self::FILTER_INTERNAL:
1668  case self::FILTER_NOT_INTERNAL:
1669  $where = 'WHERE '.$ilDB->in('rbac_fa.rol_id',$this->getGlobalRoles(),true,'integer');
1670  break;
1671 
1672  // all role templates
1673  case self::FILTER_TEMPLATES:
1674  $where = "WHERE object_data.type = 'rolt'";
1675  $assign = "n";
1676  break;
1677 
1678  // only assigned roles, handled by ilObjUserGUI::roleassignmentObject()
1679  case 0:
1680  default:
1681  if(!$a_user_id)
1682  return array();
1683 
1684  $where = 'WHERE '.$ilDB->in('rbac_fa.rol_id',$this->assignedRoles($a_user_id),false,'integer').' ';
1685  break;
1686  }
1687 
1688  $roles = array();
1689 
1690  $query = "SELECT * FROM object_data ".
1691  "JOIN rbac_fa ON obj_id = rol_id ".
1692  $where.
1693  "AND rbac_fa.assign = ".$ilDB->quote($assign,'text')." ";
1694 
1695  if(strlen($title_filter))
1696  {
1697  $query .= (' AND '.$ilDB->like(
1698  'title',
1699  'text',
1700  '%'.$title_filter.'%'
1701  ));
1702  }
1703 
1704  $res = $ilDB->query($query);
1705  while($row = $ilDB->fetchAssoc($res))
1706  {
1707  $prefix = (substr($row["title"],0,3) == "il_") ? true : false;
1708 
1709  // all (assignable) internal local roles only
1710  if ($a_filter == 4 and !$prefix)
1711  {
1712  continue;
1713  }
1714 
1715  // all (assignable) non internal local roles only
1716  if ($a_filter == 5 and $prefix)
1717  {
1718  continue;
1719  }
1720 
1721  $row["desc"] = $row["description"];
1722  $row["user_id"] = $row["owner"];
1723  $roles[] = $row;
1724  }
1725 
1726  $roles = $this->__setRoleType($roles);
1727 
1728  return $roles ? $roles : array();
1729  }
1730 
1731  // get id of a given object type (string)
1732  function getTypeId($a_type)
1733  {
1734  global $ilDB;
1735 
1736  $q = "SELECT obj_id FROM object_data ".
1737  "WHERE title=".$ilDB->quote($a_type ,'text')." AND type='typ'";
1738  $r = $ilDB->query($q);
1739 
1740  $row = $r->fetchRow(DB_FETCHMODE_OBJECT);
1741  return $row->obj_id;
1742  }
1743 
1753  public static function _getOperationIdsByName($operations)
1754  {
1755  global $ilDB;
1756 
1757  if(!count($operations))
1758  {
1759  return array();
1760  }
1761 
1762  $query = 'SELECT ops_id FROM rbac_operations '.
1763  'WHERE '.$ilDB->in('operation',$operations,false,'text');
1764 
1765  $res = $ilDB->query($query);
1766  while($row = $ilDB->fetchObject($res))
1767  {
1768  $ops_ids[] = $row->ops_id;
1769  }
1770  return $ops_ids ? $ops_ids : array();
1771  }
1772 
1780  public static function _getOperationIdByName($a_operation)
1781  {
1782  global $ilDB,$ilErr;
1783 
1784  if (!isset($a_operation))
1785  {
1786  $message = "perm::getOperationId(): No operation given!";
1787  $ilErr->raiseError($message,$ilErr->WARNING);
1788  }
1789 
1790  // Cache operation ids
1791  if (! is_array(self::$_opsCache)) {
1792  self::$_opsCache = array();
1793 
1794  $q = "SELECT ops_id, operation FROM rbac_operations";
1795  $r = $ilDB->query($q);
1796  while ($row = $r->fetchRow(DB_FETCHMODE_OBJECT))
1797  {
1798  self::$_opsCache[$row->operation] = $row->ops_id;
1799  }
1800  }
1801 
1802  // Get operation ID by name from cache
1803  if (array_key_exists($a_operation, self::$_opsCache)) {
1804  return self::$_opsCache[$a_operation];
1805  }
1806  return null;
1807  }
1808 
1814  public static function lookupCreateOperationIds($a_type_arr)
1815  {
1816  global $ilDB;
1817 
1818  $operations = array();
1819  foreach($a_type_arr as $type)
1820  {
1821  $operations[] = ('create_'.$type);
1822  }
1823 
1824  if(!count($operations))
1825  {
1826  return array();
1827  }
1828 
1829  $query = 'SELECT ops_id, operation FROM rbac_operations '.
1830  'WHERE '.$ilDB->in('operation',$operations,false,'text');
1831 
1832  $res = $ilDB->query($query);
1833 
1834  $ops_ids = array();
1835  while($row = $ilDB->fetchObject($res))
1836  {
1837  $type_arr = explode('_', $row->operation);
1838  $type = $type_arr[1];
1839 
1840  $ops_ids[$type] = $row->ops_id;
1841  }
1842  return $ops_ids;
1843  }
1844 
1845 
1854  function getLinkedRolesOfRoleFolder($a_ref_id)
1855  {
1856  global $ilDB;
1857 
1858  if (!isset($a_ref_id))
1859  {
1860  $message = get_class($this)."::getLinkedRolesOfRoleFolder(): No ref_id given!";
1861  $this->ilErr->raiseError($message,$this->ilErr->WARNING);
1862  }
1863 
1864  $and = " AND assign='n'";
1865 
1866  $query = "SELECT rol_id FROM rbac_fa ".
1867  "WHERE parent = ".$ilDB->quote($a_ref_id,'integer')." ".
1868  $and;
1869  $res = $this->ilDB->query($query);
1870  while($row = $ilDB->fetchObject($res))
1871  {
1872  $rol_id[] = $row->rol_id;
1873  }
1874 
1875  return $rol_id ? $rol_id : array();
1876  }
1877 
1878  // checks if default permission settings of role under current parent (rolefolder) are protected from changes
1879  function isProtected($a_ref_id,$a_role_id)
1880  {
1881  global $ilDB;
1882 
1883  $query = "SELECT protected FROM rbac_fa ".
1884  "WHERE rol_id = ".$ilDB->quote($a_role_id,'integer')." ".
1885  "AND parent = ".$ilDB->quote($a_ref_id,'integer')." ";
1886  $res = $ilDB->query($query);
1887  $row = $ilDB->fetchAssoc($res);
1888 
1889  return ilUtil::yn2tf($row['protected']);
1890  }
1891 
1892  // this method alters the protected status of role regarding the current user's role assignment
1893  // and current postion in the hierarchy.
1894  function __setProtectedStatus($a_parent_roles,$a_role_hierarchy,$a_ref_id)
1895  {
1896  //vd('refId',$a_ref_id,'parent roles',$a_parent_roles,'role-hierarchy',$a_role_hierarchy);
1897 
1898  global $rbacsystem,$ilUser,$log;
1899 
1900  if (in_array(SYSTEM_ROLE_ID,$this->assignedRoles($ilUser->getId())))
1901  {
1902  $leveladmin = true;
1903  }
1904  else
1905  {
1906  $leveladmin = false;
1907  }
1908  #vd("RoleHierarchy",$a_role_hierarchy);
1909  foreach ($a_role_hierarchy as $role_id => $rolf_id)
1910  {
1911  //$log->write("ilRBACreview::__setProtectedStatus(), 0");
1912  #echo "<br/>ROLF: ".$rolf_id." ROLE_ID: ".$role_id." (".$a_parent_roles[$role_id]['title'].") ";
1913  //var_dump($leveladmin,$a_parent_roles[$role_id]['protected']);
1914 
1915  if ($leveladmin == true)
1916  {
1917  $a_parent_roles[$role_id]['protected'] = false;
1918  continue;
1919  }
1920 
1921  if ($a_parent_roles[$role_id]['protected'] == true)
1922  {
1923  $arr_lvl_roles_user = array_intersect($this->assignedRoles($ilUser->getId()),array_keys($a_role_hierarchy,$rolf_id));
1924 
1925  #vd("intersection",$arr_lvl_roles_user);
1926 
1927  foreach ($arr_lvl_roles_user as $lvl_role_id)
1928  {
1929  #echo "<br/>level_role: ".$lvl_role_id;
1930  #echo "<br/>a_ref_id: ".$a_ref_id;
1931 
1932  //$log->write("ilRBACreview::__setProtectedStatus(), 1");
1933  // check if role grants 'edit_permission' to parent
1934  $rolf = $a_parent_roles[$role_id]['parent'];
1935  $parent_obj = $GLOBALS['tree']->getParentId($rolf);
1936  if ($rbacsystem->checkPermission($parent_obj,$lvl_role_id,'edit_permission'))
1937  {
1938  #echo "<br />Permission granted";
1939  //$log->write("ilRBACreview::__setProtectedStatus(), 2");
1940  // user may change permissions of that higher-ranked role
1941  $a_parent_roles[$role_id]['protected'] = false;
1942 
1943  // remember successful check
1944  //$leveladmin = true;
1945  }
1946  }
1947  }
1948  }
1949 
1950  return $a_parent_roles;
1951  }
1952 
1963  public static function _getOperationList($a_type = null)
1964  {
1965  global $ilDB;
1966 
1967  $arr = array();
1968 
1969  if ($a_type)
1970  {
1971  $query = sprintf('SELECT * FROM rbac_operations '.
1972  'JOIN rbac_ta ON rbac_operations.ops_id = rbac_ta.ops_id '.
1973  'JOIN object_data ON rbac_ta.typ_id = object_data.obj_id '.
1974  'WHERE object_data.title = %s '.
1975  'AND object_data.type = %s '.
1976  'ORDER BY op_order ASC',
1977  $ilDB->quote($a_type,'text'),
1978  $ilDB->quote('typ','text'));
1979  }
1980  else
1981  {
1982  $query = 'SELECT * FROM rbac_operations ORDER BY op_order ASC';
1983  }
1984  $res = $ilDB->query($query);
1985  while ($row = $ilDB->fetchAssoc($res))
1986  {
1987  $arr[] = array(
1988  "ops_id" => $row['ops_id'],
1989  "operation" => $row['operation'],
1990  "desc" => $row['description'],
1991  "class" => $row['class'],
1992  "order" => $row['op_order']
1993  );
1994  }
1995  return $arr;
1996  }
1997 
1998  public static function _groupOperationsByClass($a_ops_arr)
1999  {
2000  $arr = array();
2001 
2002  foreach ($a_ops_arr as $ops)
2003  {
2004  $arr[$ops['class']][] = array ('ops_id' => $ops['ops_id'],
2005  'name' => $ops['operation']
2006  );
2007  }
2008  return $arr;
2009  }
2010 
2018  public function getObjectOfRole($a_role_id)
2019  {
2020  // internal cache
2021  static $obj_cache = array();
2022 
2023  global $ilDB;
2024 
2025 
2026  if(isset($obj_cache[$a_role_id]) and $obj_cache[$a_role_id])
2027  {
2028  return $obj_cache[$a_role_id];
2029  }
2030 
2031  $query = "SELECT obr.obj_id FROM rbac_fa rfa ".
2032  "JOIN tree ON rfa.parent = tree.child ".
2033  "JOIN object_reference obr ON tree.parent = obr.ref_id ".
2034  "WHERE tree.tree = 1 ".
2035  "AND assign = 'y' ".
2036  "AND rol_id = ".$ilDB->quote($a_role_id,'integer')." ";
2037  $res = $ilDB->query($query);
2038 
2039  $obj_cache[$a_role_id] = 0;
2040  while($row = $ilDB->fetchObject($res))
2041  {
2042  $obj_cache[$a_role_id] = $row->obj_id;
2043  }
2044  return $obj_cache[$a_role_id];
2045  }
2046 
2052  public function getObjectReferenceOfRole($a_role_id)
2053  {
2054  global $ilDB;
2055 
2056  $query = "SELECT tree.parent ref FROM rbac_fa fa ".
2057  "JOIN tree ON fa.parent = tree.child ".
2058  "WHERE tree.tree = 1 ".
2059  "AND assign = ".$ilDB->quote('y','text').' '.
2060  "AND rol_id = ".$ilDB->quote($a_role_id,'integer');
2061 
2062  $res = $ilDB->query($query);
2063  while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
2064  {
2065  return $row->ref;
2066  }
2067  return 0;
2068  }
2069 
2076  public function isRoleDeleted ($a_role_id){
2077  $rolf_list = $this->getFoldersAssignedToRole($a_role_id, false);
2078  $deleted = true;
2079  if (count($rolf_list))
2080  {
2081  foreach ($rolf_list as $rolf) {
2082  // only list roles that are not set to status "deleted"
2083  if (!$this->isDeleted($rolf))
2084  {
2085  $deleted = false;
2086  break;
2087  }
2088  }
2089  }
2090  return $deleted;
2091  }
2092 
2093 
2094  function getRolesForIDs($role_ids, $use_templates)
2095  {
2096  global $ilDB;
2097 
2098  $role_list = array();
2099 
2100  $where = $this->__setTemplateFilter($use_templates);
2101 
2102  $query = "SELECT * FROM object_data ".
2103  "JOIN rbac_fa ON object_data.obj_id = rbac_fa.rol_id ".
2104  $where.
2105  "AND rbac_fa.assign = 'y' " .
2106  'AND '.$ilDB->in('object_data.obj_id',$role_ids,false,'integer');
2107 
2108  $res = $ilDB->query($query);
2109  while($row = $ilDB->fetchAssoc($res))
2110  {
2111  $row["desc"] = $row["description"];
2112  $row["user_id"] = $row["owner"];
2113  $role_list[] = $row;
2114  }
2115 
2116  $role_list = $this->__setRoleType($role_list);
2117  return $role_list;
2118  }
2119 
2124  public function getOperationAssignment()
2125  {
2126  global $ilDB;
2127 
2128  $query = 'SELECT ta.typ_id, obj.title, ops.ops_id, ops.operation FROM rbac_ta ta '.
2129  'JOIN object_data obj ON obj.obj_id = ta.typ_id '.
2130  'JOIN rbac_operations ops ON ops.ops_id = ta.ops_id ';
2131  $res = $ilDB->query($query);
2132 
2133  $counter = 0;
2134  while($row = $ilDB->fetchObject($res))
2135  {
2136  $info[$counter]['typ_id'] = $row->typ_id;
2137  $info[$counter]['type'] = $row->title;
2138  $info[$counter]['ops_id'] = $row->ops_id;
2139  $info[$counter]['operation'] = $row->operation;
2140  $counter++;
2141  }
2142  return $info ? $info : array();
2143 
2144  }
2145 
2154  public function filterEmptyRoleFolders($a_rolf_candidates)
2155  {
2156  global $ilDB;
2157 
2158  $query = 'SELECT DISTINCT(parent) parent FROM rbac_fa '.
2159  'WHERE '.$ilDB->in('parent',$a_rolf_candidates,false,'integer');
2160  $res = $ilDB->query($query);
2161  while($row = $ilDB->fetchObject($res))
2162  {
2163  $non_empty[] = $row->parent;
2164  }
2165  return $non_empty ? $non_empty : array();
2166  }
2167 
2174  public function isDeleteable($a_role_id, $a_rolf_id)
2175  {
2176  if(!$this->isAssignable($a_role_id, $a_rolf_id))
2177  {
2178  return false;
2179  }
2180  if($a_role_id == SYSTEM_ROLE_ID or $a_role_id == ANONYMOUS_ROLE_ID)
2181  {
2182  return false;
2183  }
2184  if(substr(ilObject::_lookupTitle($a_role_id),0,3) == 'il_')
2185  {
2186  return false;
2187  }
2188  return true;
2189  }
2190 
2196  public function isSystemGeneratedRole($a_role_id)
2197  {
2198  $title = ilObject::_lookupTitle($a_role_id);
2199  return substr($title,0,3) == 'il_' ? true : false;
2200  }
2201 
2202 
2209  public function getRoleFolderOfRole($a_role_id)
2210  {
2211  global $ilDB;
2212 
2213  if(ilObject::_lookupType($a_role_id) == 'role')
2214  {
2215  $and = ('AND assign = '.$ilDB->quote('y','text'));
2216  }
2217  else
2218  {
2219  $and = '';
2220  }
2221 
2222  $query = 'SELECT * FROM rbac_fa '.
2223  'WHERE rol_id = '.$ilDB->quote($a_role_id,'integer').' '.
2224  $and;
2225  $res = $ilDB->query($query);
2226  while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
2227  {
2228  return $row->parent;
2229  }
2230  return 0;
2231  }
2232 
2239  function getUserPermissionsOnObject($a_user_id, $a_ref_id)
2240  {
2241  global $ilDB;
2242 
2243  $query = "SELECT ops_id FROM rbac_pa JOIN rbac_ua ".
2244  "ON (rbac_pa.rol_id = rbac_ua.rol_id) ".
2245  "WHERE rbac_ua.usr_id = ".$ilDB->quote($a_user_id,'integer')." ".
2246  "AND rbac_pa.ref_id = ".$ilDB->quote($a_ref_id,'integer')." ";
2247 
2248  $res = $ilDB->query($query);
2249  $all_ops = array();
2250  while ($row = $ilDB->fetchObject($res))
2251  {
2252  $ops = unserialize($row->ops_id);
2253  $all_ops = array_merge($all_ops, $ops);
2254  }
2255  $all_ops = array_unique($all_ops);
2256 
2257  $set = $ilDB->query("SELECT operation FROM rbac_operations ".
2258  " WHERE ".$ilDB->in("ops_id", $all_ops, false, "integer"));
2259  $perms = array();
2260  while ($rec = $ilDB->fetchAssoc($set))
2261  {
2262  $perms[] = $rec["operation"];
2263  }
2264 
2265  return $perms;
2266  }
2267 
2268 } // END class.ilRbacReview
2269 ?>