ILIAS  release_4-3 Revision
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.ilCtrl.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2012 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
11 class ilCtrl
12 {
13  const IL_RTOKEN_NAME = 'rtoken';
14 
16  var $forward; // forward array
17  var $parent; // parent array (reverse forward)
18  var $save_parameter; // save parameter array
19  var $return; // return commmands
20  var $call_hist = array(); // calling history
21  var $debug = array();
22  var $calls = array();
23  var $rtoken = false;
24 
28  function ilCtrl()
29  {
30  global $ilBench;
31 
32  $this->bench =& $ilBench;
33 
34  // initialisation
35  $this->init();
36 
37  // this information should go to xml files one day
38  $this->stored_trees = array
39  ("ilrepositorygui", "ilpersonaldesktopgui",
40  "illmpresentationgui", "illmeditorgui",
41  "iladministrationgui");
42  }
43 
49  function debug($str)
50  {
51  $this->debug[] = $str;
52  }
53 
59  function getDebug()
60  {
61  return $this->debug;
62  }
63 
67  function init()
68  {
69  $this->transit = array();
70  $this->forward = array(); // forward array
71  $this->forwards = array(); // forward array
72  $this->parent = array(); // parent array (reverse forward)
73  $this->save_parameter = array(); // save parameter array
74  $this->parameter = array(); // save parameter array
75  $this->return = ""; // return commmands
76  $this->location = array();
77  $this->tab = array();
78  $this->current_node = 0;
79  $this->module_dir = "";
80  $this->service_dir = "";
81  $this->call_node = array();
82  $this->root_class = "";
83  }
84 
91  function callBaseClass()
92  {
93  global $ilDB;
94 
95  $baseClass = strtolower($_GET["baseClass"]);
96 
97  // get class information
98  $mc_set = $ilDB->query("SELECT * FROM module_class WHERE LOWER(class) = ".
99  $ilDB->quote($baseClass, "text"));
100  $mc_rec = $ilDB->fetchAssoc($mc_set);
101  $module = $mc_rec["module"];
102  $class = $mc_rec["class"];
103  $class_dir = $mc_rec["dir"];
104 
105  if ($module != "")
106  {
107  $m_set = $ilDB->query("SELECT * FROM il_component WHERE name = ".
108  $ilDB->quote($module, "text"));
109  $m_rec = $ilDB->fetchAssoc($m_set);
110  $this->module_dir = $m_rec["type"]."/".$m_rec["name"];
111  include_once $this->module_dir."/".$class_dir."/class.".$class.".php";
112  }
113  else // check whether class belongs to a service
114  {
115  $mc_set = $ilDB->query("SELECT * FROM service_class WHERE LOWER(class) = ".
116  $ilDB->quote($baseClass, "text"));
117  $mc_rec = $ilDB->fetchAssoc($mc_set);
118 
119  $service = $mc_rec["service"];
120  $class = $mc_rec["class"];
121  $class_dir = $mc_rec["dir"];
122 
123  if ($service == "")
124  {
125  include_once("./Services/UICore/exceptions/class.ilCtrlException.php");
126  throw new ilCtrlException("Could not find entry in modules.xml or services.xml for ".
127  $baseClass." <br/>".str_replace("&", "<br />&", htmlentities($_SERVER["REQUEST_URI"])));
128  }
129 
130  // get service information
131  $m_set = $ilDB->query("SELECT * FROM il_component WHERE name = ".
132  $ilDB->quote($service, "text"));
133  $m_rec = $ilDB->fetchAssoc($m_set);
134  $this->service_dir = $m_rec["type"]."/".$m_rec["name"];
135 
136  include_once $this->service_dir."/".$class_dir."/class.".$class.".php";;
137  }
138 
139  // forward processing to base class
140  $this->getCallStructure(strtolower($baseClass));
141  $base_class_gui =& new $class();
142  $this->forwardCommand($base_class_gui);
143  }
144 
148  function getModuleDir()
149  {
150  return $this->module_dir;
151  }
152 
162  function &forwardCommand(&$a_gui_object)
163  {
164  $class = strtolower(get_class($a_gui_object));
165 //echo "<br>class:".$class.":";
166  $nr = $this->getNodeIdForTargetClass($this->current_node, $class);
167  $nr = $nr["node_id"];
168  if ($nr != "")
169  {
170  $current_node = $this->current_node;
171 
172  $this->current_node = $nr;
173 
174  // always populate the call history
175  // it will only be displayed in DEVMODE but is needed for UI plugins, too
176  $this->call_hist[] = array("class" => get_class($a_gui_object),
177  "mode" => "execComm", "cmd" => $this->getCmd());
178 
179 //echo "<br>class:".get_class($a_gui_object).":";
180  $html = $a_gui_object->executeCommand();
181 
182  // reset current node
183  $this->current_node = $current_node;
184 
185  return $html;
186 
187  }
188 
189  include_once("./Services/UICore/exceptions/class.ilCtrlException.php");
190  throw new ilCtrlException("ERROR: Can't forward to class $class.");
191  }
192 
200  function &getHTML(&$a_gui_object)
201  {
202  $class = strtolower(get_class($a_gui_object));
203 
204  $nr = $this->getNodeIdForTargetClass($this->current_node, $class);
205  $nr = $nr["node_id"];
206  if ($nr != "")
207  {
208  $current_node = $this->current_node;
209 
210  // set current node to new gui class
211  $this->current_node = $nr;
212 
213  // always populate the call history
214  // it will only be displayed in DEVMODE but is needed for UI plugins, too
215  $this->call_hist[] = array("class" => get_class($a_gui_object),
216  "mode" => "getHtml", "cmd" => $this->getCmd());
217 
218  // get block
219  $html = $a_gui_object->getHTML();
220 
221  // reset current node
222  $this->current_node = $current_node;
223 
224  // return block
225  return $html;
226  }
227 
228  include_once("./Services/UICore/exceptions/class.ilCtrlException.php");
229  throw new ilCtrlException("ERROR: Can't getHTML from class $class.");
230 
231  }
232 
242  function setContext($a_obj_id, $a_obj_type, $a_sub_obj_id = 0, $a_sub_obj_type = "")
243  {
244  $this->context_obj_id = $a_obj_id;
245  $this->context_obj_type = $a_obj_type;
246  $this->context_sub_obj_id = $a_sub_obj_id;
247  $this->context_sub_obj_type = $a_sub_obj_type;
248  }
249 
255  public function getContextObjId()
256  {
257  return $this->context_obj_id;
258  }
259 
265  public function getContextObjType()
266  {
267  return $this->context_obj_type;
268  }
269 
275  public function getContextSubObjId()
276  {
277  return $this->context_sub_obj_id;
278  }
279 
285  public function getContextSubObjType()
286  {
287  return $this->context_sub_obj_type;
288  }
289 
308  private function getNodeIdForTargetClass($a_par_node, $a_class, $a_check = false)
309  {
310  $class = strtolower($a_class);
311  $this->readClassInfo($class);
312 
313  if ($a_par_node === 0 || $a_par_node == "")
314  {
315  return array("node_id" => $this->getCidForClass($class),
316  "base_class" => "");
317  }
318 
319  $this->readNodeInfo($a_par_node);
320 
321  $node_cid = $this->getCurrentCidOfNode($a_par_node);
322 
323  // target class is class of current node id
324  if ($class == $this->getClassForCid($node_cid))
325  {
326  return array("node_id" => $a_par_node,
327  "base_class" => "");
328  }
329 
330  // target class is child of current node id
331  if (isset($this->calls[$this->getClassForCid($node_cid)]) &&
332  is_array($this->calls[$this->getClassForCid($node_cid)]) &&
333  in_array($a_class, $this->calls[$this->getClassForCid($node_cid)]))
334  {
335  return array("node_id" => $a_par_node.":".$this->getCidForClass($class),
336  "base_class" => "");
337  }
338 
339  // target class is sibling
340  $par_cid = $this->getParentCidOfNode($a_par_node);
341  if ($par_cid != "")
342  {
343  if (is_array($this->calls[$this->getClassForCid($par_cid)]) &&
344  in_array($a_class, $this->calls[$this->getClassForCid($par_cid)]))
345  {
346  return array("node_id" =>
347  $this->removeLastCid($a_par_node).":".$this->getCidForClass($class),
348  "base_class" => "");
349  }
350  }
351 
352  // target class is parent
353  $temp_node = $this->removeLastCid($a_par_node);
354  while($temp_node != "")
355  {
356  $temp_cid = $this->getCurrentCidOfNode($temp_node);
357  if ($this->getClassForCid($temp_cid) == $a_class)
358  {
359  return array("node_id" => $temp_node,
360  "base_class" => "");
361  }
362  $temp_node = $this->removeLastCid($temp_node);
363  }
364 
365  // target class is another base class
366  $n_class = "";
367  if ($a_class != "")
368  {
369  global $ilDB;
370 
371  // get class information
372  $mc_set = $ilDB->query("SELECT * FROM module_class WHERE LOWER(class) = ".
373  $ilDB->quote($class, "text"));
374  $mc_rec = $ilDB->fetchAssoc($mc_set);
375  $n_class = strtolower($mc_rec["class"]);
376 
377  if ($n_class == "")
378  {
379  $mc_set = $ilDB->query("SELECT * FROM service_class WHERE LOWER(class) = ".
380  $ilDB->quote($class, "text"));
381  $mc_rec = $ilDB->fetchAssoc($mc_set);
382  $n_class = strtolower($mc_rec["class"]);
383  }
384 
385  if ($n_class != "")
386  {
387  $this->getCallStructure($n_class);
388  return array("node_id" => $this->getCidForClass($n_class),
389  "base_class" => $class);
390  }
391  }
392 
393  if ($a_check)
394  {
395  return false;
396  }
397 
398  // Please do NOT change these lines.
399  // Developers must be aware, if they use classes unknown to the controller
400  // otherwise certain problem will be extremely hard to track down...
401 
402 // echo "ERROR: Can't find target class $a_class for node $a_par_node ".
403 // "(".$this->cid_class[$this->getParentCidOfNode($a_par_node)].").<br>";
404  error_log( "ERROR: Can't find target class $a_class for node $a_par_node ".
405  "(".$this->cid_class[$this->getParentCidOfNode($a_par_node)].")");
406 
407  if (DEVMODE == 1)
408  {
409 // ilUtil::printBacktrace();
410  }
411 
412  include_once("./Services/UICore/exceptions/class.ilCtrlException.php");
413  throw new ilCtrlException("ERROR: Can't find target class $a_class for node $a_par_node ".
414  "(".$this->cid_class[$this->getParentCidOfNode($a_par_node)].").");
415  }
416 
423  function checkTargetClass($a_class)
424  {
425  if (!is_array($a_class))
426  {
427  $a_class = array($a_class);
428  }
429 
430  $nr = $this->current_node;
431  foreach ($a_class as $class)
432  {
433  $class = strtolower($class);
434 
435  if (!$this->getCidForClass($class, true))
436  {
437  return false;
438  }
439 
440  $nr = $this->getNodeIdForTargetClass($nr, $class, true);
441  $nr = $nr["node_id"];
442  if ($nr === false)
443  {
444  return false;
445  }
446  }
447  return true;
448  }
449 
455  function getCmdNode()
456  {
457  return $_GET["cmdNode"];
458  }
459 
467  function addLocation($a_title, $a_link, $a_target = "", $a_ref_id = 0)
468  {
469  $this->location[] = array("title" => $a_title,
470  "link" => $a_link, "target" => $a_target, "ref_id" => $a_ref_id);
471  }
472 
478  function getLocations()
479  {
480  return $this->location;
481  }
482 
491  function addTab($a_lang_var, $a_link, $a_cmd, $a_class)
492  {
493  $a_class = strtolower($a_class);
494 
495  $this->tab[] = array("lang_var" => $a_lang_var,
496  "link" => $a_link, "cmd" => $a_cmd, "class" => $a_class);
497  }
498 
504  function getTabs()
505  {
506  return $this->tab;
507  }
508 
515  function getCallHistory()
516  {
517  return $this->call_hist;
518  }
519 
536  function getCallStructure($a_class)
537  {
538  $this->readClassInfo($a_class);
539  }
540 
545 /* function storeCommonStructures()
546  {
547  global $ilDB;
548 
549  $ilDB->manipulate("DELETE FROM ctrl_structure");
550 
551  foreach ($this->stored_trees as $root_gui_class)
552  {
553  $this->call_node = array();
554  $this->forward = array();
555  $this->parent = array();
556  $this->readCallStructure($root_gui_class);
557  $ilDB->insert("ctrl_structure", array(
558  "root_class" => array("text", $root_gui_class),
559  "call_node" => array("text", serialize($this->call_node)),
560  "forward" => array("text", serialize($this->forward)),
561  "parent" => array("clob", serialize($this->parent))));
562  }
563  }
564 */
565 
569  function readCallStructure($a_class, $a_nr = 0, $a_parent = 0)
570  {
571  global $ilDB;
572 
573  $a_class = strtolower($a_class);
574 
575  $a_nr++;
576 
577  // determine call node structure
578  $this->call_node[$a_nr] = array("class" => $a_class, "parent" => $a_parent);
579 
580 //echo "<br>nr:$a_nr:class:$a_class:parent:$a_parent:";
581  $call_set = $ilDB->query("SELECT * FROM ctrl_calls WHERE parent = ".
582  $ilDB->quote(strtolower($a_class), "text").
583  " ORDER BY child", array("text"));
584  $a_parent = $a_nr;
585  while ($call_rec = $ilDB->fetchAssoc($call_set))
586  {
587  $a_nr = $this->readCallStructure($call_rec["child"], $a_nr, $a_parent);
588  $forw[] = $call_rec["child"];
589  }
590 
591  // determin forward and parent array
592  $this->forwards($a_class, $forw);
593 //echo "<br>forwards:".$a_class."<br>"; var_dump($forw);
594 
595  // determine root class
596  $this->root_class = $a_class;
597  return $a_nr;
598  }
599 
600 
607  private function forwards($a_from_class, $a_to_class)
608  {
609  $a_from_class = strtolower($a_from_class);
610 
611  if (is_array($a_to_class))
612  {
613  foreach($a_to_class as $to_class)
614  {
615  if ($a_from_class != "" && $to_class != "")
616  {
617  if (!is_array($this->forward[$a_from_class]) || !in_array(strtolower($to_class), $this->forward[$a_from_class]))
618  {
619  $this->forward[$a_from_class][] = strtolower($to_class);
620  }
621  if (!is_array($this->parent[strtolower($to_class)]) || !in_array($a_from_class, $this->parent[strtolower($to_class)]))
622  {
623  $this->parent[strtolower($to_class)][] = $a_from_class;
624  }
625  }
626  }
627  }
628  else
629  {
630  $to_class = $a_to_class;
631  if ($a_from_class != "" && $to_class != "")
632  {
633  if (!is_array($this->forward[$a_from_class]) || !in_array(strtolower($to_class), $this->forward[$a_from_class]))
634  {
635  $this->forward[$a_from_class][] = strtolower($to_class);
636  }
637  if (!is_array($this->parent[strtolower($to_class)]) || !in_array($a_from_class, $this->parent[strtolower($to_class)]))
638  {
639  $this->parent[strtolower($to_class)][] = $a_from_class;
640  }
641  }
642  }
643  }
644 
645 
665  public function saveParameter(&$a_obj, $a_parameter)
666  {
667  if (is_object($a_obj))
668  {
669  $this->saveParameterByClass(get_class($a_obj), $a_parameter);
670  }
671  }
672 
679  function saveParameterByClass($a_class, $a_parameter)
680  {
681  if (is_array($a_parameter))
682  {
683  foreach($a_parameter as $parameter)
684  {
685  $this->save_parameter[strtolower($a_class)][] = $parameter;
686  }
687  }
688  else
689  {
690  $this->save_parameter[strtolower($a_class)][] = $a_parameter;
691  }
692  }
693 
694 
717  public function setParameter(&$a_obj, $a_parameter, $a_value)
718  {
719  $this->parameter[strtolower(get_class($a_obj))][$a_parameter] = $a_value;
720  }
721 
722 
730  public function setParameterByClass($a_class, $a_parameter, $a_value)
731  {
732  $this->parameter[strtolower($a_class)][$a_parameter] = $a_value;
733  }
734 
735 
742  public function clearParameters(&$a_obj)
743  {
744  $this->clearParametersByClass(strtolower(get_class($a_obj)));
745  }
746 
753  public function clearParametersByClass($a_class)
754  {
755  $this->parameter[strtolower($a_class)] = array();
756  }
757 
766  function getNextClass()
767  {
768  $cmdNode = $this->getCmdNode();
769 //echo "<br>getNextClass (current node: ".$this->current_node."; cmd node: ".$cmdNode.") ";
770  if ($cmdNode == "")
771  {
772  return false;
773  }
774  else
775  {
776  if ($this->current_node == $cmdNode)
777  {
778 //echo "1:".$this->call_node[$cmdNode]["class"]."<br>";
779  //return $this->call_node[$cmdNode]["class"];
780  return "";
781  }
782  else
783  {
784  $path = $this->getPathNew($this->current_node, $cmdNode);
785 //var_dump($path);
786 //echo " - Next Node: ".$path[1];
787  $this->readCidInfo($this->getCurrentCidOfNode($path[1]));
788 //echo ":".$this->cid_class[$this->getCurrentCidOfNode($path[1])].":".$this->getCurrentCidOfNode($path[1]).":";
789  return $this->cid_class[$this->getCurrentCidOfNode($path[1])];
790  }
791  }
792  }
793 
800  function lookupClassPath($a_class_name)
801  {
802  global $ilDB;
803  $a_class_name = strtolower($a_class_name);
804 
805  $class_set = $ilDB->query("SELECT * FROM ctrl_classfile WHERE class = ".
806  $ilDB->quote($a_class_name, "text"));
807  $class_rec = $ilDB->fetchAssoc($class_set);
808 
809  if ($class_rec["plugin_path"] != "")
810  {
811  return $class_rec["plugin_path"]."/".$class_rec["filename"];
812  }
813  else
814  {
815  return $class_rec["filename"];
816  }
817  }
818 
827  function getClassForClasspath($a_class_path)
828  {
829  $path = pathinfo($a_class_path);
830  $file = $path["basename"];
831  $class = substr($file, 6, strlen($file) - 10);
832 
833  return $class;
834  }
835 
842  private function getPathNew($a_source_node, $a_target_node)
843  {
844 //if ($this->getCmdClass() == "ilmailfoldergui") echo "-".$a_source_node."-".$a_target_node."-";
845 //echo "-".$a_source_node."-".$a_target_node."-";
846 //echo "<br>:::$a_source_node:::";
847  if ($a_source_node == "1")
848  {
849  $a_source_node = "";
850  }
851  if (substr($a_target_node, 0, strlen($a_source_node)) != $a_source_node)
852  {
853  $failure = "ERROR: Path not found. Source:".$a_source_node.
854  ", Target:".$a_target_node;
855  if (DEVMODE == 1)
856  {
857  include_once("./Services/UICore/exceptions/class.ilCtrlException.php");
858  throw new ilCtrlException($failure);
859  }
860  $GLOBALS['ilLog']->write(__METHOD__.' '.$failure);
861  ilUtil::redirect('./ilias.php?baseClass=ilRepositoryGUI');
862  }
863 //echo "<br>:::$a_source_node:::";
864  $temp_node = $a_source_node;
865 
866  $path = array();
867  if ($a_source_node != "")
868  {
869  $path = array($a_source_node);
870  }
871 
872  $diffstart = ($a_source_node == "")
873  ? 0
874  : strlen($a_source_node) + 1;
875  $diff = substr($a_target_node, $diffstart);
876 //echo "=$diff=$diffstart=";
877  $diff_arr = explode(":", $diff);
878  foreach($diff_arr as $cid)
879  {
880  if ($temp_node != "")
881  {
882  $temp_node.= ":";
883  }
884  $temp_node.= $cid;
885  $path[] = $temp_node;
886  }
887 //if ($this->getCmdClass() == "ilmailfoldergui") var_dump($path);
888 //var_dump($path);
889  return $path;
890  }
891 
897  public function setTargetScript($a_target_script)
898  {
899  $this->target_script = $a_target_script;
900  }
901 
902 
908  public function getTargetScript()
909  {
910  return $this->target_script;
911  }
912 
913 
922  public function initBaseClass($a_base_class)
923  {
924  $_GET["baseClass"] = $a_base_class;
925  $_GET["cmd"] = "";
926  $_GET["cmdClass"] = "";
927  $_GET["cmdNode"] = "";
928  $this->init();
929  }
930 
938  public function getCmd($a_default_cmd = "", $a_safe_commands = "")
939  {
940  $cmd = "";
941  if (isset($_GET["cmd"]))
942  {
943  $cmd = $_GET["cmd"];
944  }
945  if($cmd == "post")
946  {
947  if (isset($_POST["cmd"]) && is_array($_POST["cmd"]))
948  {
949  reset($_POST["cmd"]);
950  }
951  $cmd = @key($_POST["cmd"]);
952 
953  // verify command
954  if ($this->verified_cmd != "")
955  {
956  return $this->verified_cmd;
957  }
958  else
959  {
960  if (!$this->verifyToken() &&
961  (!is_array($a_safe_commands) || !in_array($cmd, $a_safe_commands)))
962  {
963  return $a_default_cmd;
964  }
965  }
966 
967  $this->verified_cmd = $cmd;
968  if($cmd == "" && isset($_POST["table_top_cmd"])) // selected command in multi-list (table2)
969  {
970  $cmd = @key($_POST["table_top_cmd"]);
971  $this->verified_cmd = $cmd;
972  $_POST[$_POST["cmd_sv"][$cmd]] = $_POST[$_POST["cmd_sv"][$cmd]."_2"];
973  }
974  if($cmd == "" && isset($_POST["select_cmd2"])) // selected command in multi-list (table2)
975  {
976  if(isset($_POST["select_cmd_all2"]))
977  {
978  $_POST["select_cmd_all"] = $_POST["select_cmd_all2"];
979  }
980  else
981  {
982  $_POST["select_cmd_all"] = $_POST["select_cmd_all2"] = null;
983  }
984  $cmd = $_POST["selected_cmd2"];
985  $this->verified_cmd = $cmd;
986  }
987  if($cmd == "" && isset($_POST["select_cmd"])) // selected command in multi-list (table2)
988  {
989  if(isset($_POST["select_cmd_all"]))
990  {
991  $_POST["select_cmd_all2"] = $_POST["select_cmd_all"];
992  }
993  else
994  {
995  $_POST["select_cmd_all"] = $_POST["select_cmd_all2"] = null;
996  }
997  $cmd = $_POST["selected_cmd"];
998  $this->verified_cmd = $cmd;
999  }
1000  if($cmd == "")
1001  {
1002  $cmd = $_GET["fallbackCmd"];
1003  $this->verified_cmd = $cmd;
1004  }
1005  }
1006  if($cmd == "")
1007  {
1008  $cmd = $a_default_cmd;
1009  }
1010  return $cmd;
1011  }
1012 
1023  function setCmd($a_cmd)
1024  {
1025  $_GET["cmd"] = $a_cmd;
1026  }
1027 
1038  public function setCmdClass($a_cmd_class)
1039  {
1040  $a_cmd_class = strtolower($a_cmd_class);
1041  $nr = $this->getNodeIdForTargetClass($this->current_node, $a_cmd_class);
1042  $nr = $nr["node_id"];
1043  $_GET["cmdClass"] = $a_cmd_class;
1044  $_GET["cmdNode"] = $nr;
1045  }
1046 
1052  function getCmdClass()
1053  {
1054  return strtolower($_GET["cmdClass"]);
1055  }
1056 
1067  function getFormAction(&$a_gui_obj, $a_fallback_cmd = "", $a_anchor = "", $a_asynch = false,
1068  $xml_style = true)
1069  {
1070  $script = $this->getFormActionByClass(strtolower(get_class($a_gui_obj)),
1071  $a_fallback_cmd, $a_anchor, $a_asynch, $xml_style);
1072  return $script;
1073  }
1074 
1085  function getFormActionByClass($a_class, $a_fallback_cmd = "", $a_anchor = "", $a_asynch = false,
1086  $xml_style = true)
1087  {
1088  if(!is_array($a_class))
1089  {
1090  $a_class = strtolower($a_class);
1091  }
1092 
1093  $tok = $this->getRequestToken();
1094 
1095  if ($a_asynch)
1096  {
1097  $xml_style = false;
1098  }
1099 
1100  $script = $this->getLinkTargetByClass($a_class, "post", "", $a_asynch);
1101  if ($a_fallback_cmd != "")
1102  {
1103  $script = ilUtil::appendUrlParameterString($script, "fallbackCmd=".$a_fallback_cmd, $xml_style);
1104  }
1105  $script = ilUtil::appendUrlParameterString($script, self::IL_RTOKEN_NAME.'='.$this->getRequestToken(),
1106  $xml_style);
1107  if ($a_anchor != "")
1108  {
1109  $script = $script."#".$a_anchor;
1110  }
1111 
1112  return $script;
1113  }
1114 
1121  public function appendRequestTokenParameterString($a_url, $xml_style = true)
1122  {
1123  return ilUtil::appendUrlParameterString($a_url, self::IL_RTOKEN_NAME.'='.$this->getRequestToken(),
1124  $xml_style);
1125  }
1126 
1132  public function getRequestToken()
1133  {
1134  global $ilDB, $ilUser;
1135 
1136  if ($this->rtoken != "")
1137  {
1138  return $this->rtoken;
1139  }
1140  else
1141  {
1142  if (is_object($ilDB) && is_object($ilUser) && $ilUser->getId() > 0 &&
1143  $ilUser->getId() != ANONYMOUS_USER_ID)
1144  {
1145  $res = $ilDB->query("SELECT token FROM il_request_token WHERE user_id = ".
1146  $ilDB->quote($ilUser->getId(), "integer").
1147  " AND session_id = ".$ilDB->quote(session_id(), "text"));
1148  $rec = $ilDB->fetchAssoc($res);
1149 
1150  if ($rec["token"] != "")
1151  {
1152  $this->rtoken = $rec["token"];
1153  return $rec["token"];
1154  }
1155 
1156  $this->rtoken = md5(uniqid(rand(), true));
1157 
1158  // delete entries older than one and a half days
1159  if (rand(1, 200) == 2)
1160  {
1161  $dt = new ilDateTime(time(),IL_CAL_UNIX);
1162  $dt->increment(IL_CAL_DAY, -1);
1163  $dt->increment(IL_CAL_HOUR, -12);
1164  $dq = "DELETE FROM il_request_token WHERE ".
1165  " stamp < ".$ilDB->quote($dt->get(IL_CAL_DATETIME), "timestamp");
1166  $ilDB->manipulate($dq);
1167  }
1168 
1169  // IMPORTANT: Please do NOT try to move this implementation to a
1170  // session basis. This will fail due to framesets that are used
1171  // occasionally in ILIAS, e.g. in the chat, where multiple
1172  // forms are loaded in different frames.
1173  $ilDB->manipulate("INSERT INTO il_request_token (user_id, token, stamp, session_id) VALUES ".
1174  "(".
1175  $ilDB->quote($ilUser->getId(), "integer").",".
1176  $ilDB->quote($this->rtoken, "text").",".
1177  $ilDB->now().",".
1178  $ilDB->quote(session_id(), "text").")");
1179  return $this->rtoken;
1180  }
1181  //$this->rtoken = md5(uniqid(rand(), true));
1182  }
1183  return "";
1184  }
1185 
1191  private function verifyToken()
1192  {
1193  global $ilDB, $ilUser;
1194 
1195  if (is_object($ilUser) && is_object($ilDB) && $ilUser->getId() > 0 &&
1196  $ilUser->getId() != ANONYMOUS_USER_ID)
1197  {
1198  if ($_GET["rtoken"] == "")
1199  {
1200  #echo "ilCtrl::No Request Token Given!"; // for debugging, maybe changed later
1201  return false;
1202  }
1203 
1204  $set = $ilDB->query("SELECT * FROM il_request_token WHERE ".
1205  " user_id = ".$ilDB->quote($ilUser->getId(), "integer")." AND ".
1206  " token = ".$ilDB->quote($_GET[self::IL_RTOKEN_NAME]), "text");
1207  if ($ilDB->numRows($set) > 0)
1208  {
1209  // remove used token
1210  /*
1211  $ilDB->query("DELETE FROM il_request_token WHERE ".
1212  " user_id = ".$ilDB->quote($ilUser->getId())." AND ".
1213  " token = ".$ilDB->quote($_GET[self::IL_RTOKEN_NAME]));
1214  */
1215 
1216  // remove tokens from older sessions
1217  $ilDB->manipulate("DELETE FROM il_request_token WHERE ".
1218  " user_id = ".$ilDB->quote($ilUser->getId(), "integer")." AND ".
1219  " session_id != ".$ilDB->quote(session_id(), "text"));
1220  return true;
1221  }
1222  else
1223  {
1224  return false;
1225  }
1226 
1227  if ($_SESSION["rtokens"][$_GET[self::IL_RTOKEN_NAME]] != "")
1228  {
1229  // remove used token
1230  unset($_SESSION["rtokens"][$_GET[self::IL_RTOKEN_NAME]]);
1231 
1232  // remove old tokens
1233  if (count($_SESSION["rtokens"]) > 100)
1234  {
1235  $to_remove = array();
1236  $sec = 7200; // two hours
1237 
1238  foreach($_SESSION["rtokens"] as $tok => $time)
1239  {
1240  if (time() - $time > $sec)
1241  {
1242  $to_remove[] = $tok;
1243  }
1244  }
1245  foreach($to_remove as $tok)
1246  {
1247  unset($_SESSION["rtokens"][$tok]);
1248  }
1249  }
1250 
1251  return true;
1252  }
1253  return false;
1254  }
1255  else
1256  {
1257  return true; // do not verify, if user or db object is missing
1258  }
1259 
1260  return false;
1261  }
1262 
1270  public function redirect(&$a_gui_obj, $a_cmd = "", $a_anchor = "", $a_asynch = false)
1271  {
1272  global $ilBench;
1273 
1274  $script = $this->getLinkTargetByClass(strtolower(get_class($a_gui_obj)), $a_cmd,
1275  "", $a_asynch, false);
1276  if (is_object($ilBench))
1277  {
1278  $ilBench->save();
1279  }
1280  if ($a_anchor != "")
1281  {
1282  $script = $script."#".$a_anchor;
1283  }
1284  ilUtil::redirect($script);
1285  }
1286 
1287 
1294  public function redirectByClass($a_class, $a_cmd = "", $a_anchor = "", $a_asynch = false)
1295  {
1296  $script = $this->getLinkTargetByClass($a_class, $a_cmd, "", $a_asynch, false);
1297  if ($a_anchor != "")
1298  {
1299  $script = $script."#".$a_anchor;
1300  }
1301  ilUtil::redirect($script);
1302  }
1303 
1309  public function isAsynch()
1310  {
1311  if (isset($_GET["cmdMode"]) && $_GET["cmdMode"] == "asynch")
1312  {
1313  return true;
1314  }
1315  else
1316  {
1317  return false;
1318  }
1319  }
1320 
1321 
1333  function getLinkTarget(&$a_gui_obj, $a_cmd = "", $a_anchor = "", $a_asynch = false,
1334  $xml_style = true)
1335  {
1336  $script = $this->getLinkTargetByClass(strtolower(get_class($a_gui_obj)), $a_cmd, $a_anchor, $a_asynch,
1337  $xml_style);
1338  return $script;
1339  }
1340 
1341 
1353  function getLinkTargetByClass($a_class, $a_cmd = "", $a_anchor = "", $a_asynch = false,
1354  $xml_style = true)
1355  {
1356  if ($a_asynch)
1357  {
1358  $xml_style = false;
1359  }
1360 
1361  // note: $a_class may be an array
1362  //$a_class = strtolower($a_class);
1363 
1364 //echo "<br>getLinkTargetByClass";
1365  $script = $this->getTargetScript();
1366  $script = $this->getUrlParameters($a_class, $script, $a_cmd, $xml_style);
1367 
1368  if ($a_asynch)
1369  {
1370  //$amp = $xml_style
1371  // ? "&amp;"
1372  // : "&";
1373  $amp = "&";
1374  $script.= $amp."cmdMode=asynch";
1375  }
1376 
1377  if ($a_anchor != "")
1378  {
1379  $script = $script."#".$a_anchor;
1380  }
1381 
1382  return $script;
1383  }
1384 
1388  function setReturn(&$a_gui_obj, $a_cmd)
1389  {
1390  $script = $this->getTargetScript();
1391  $script = $this->getUrlParameters(strtolower(get_class($a_gui_obj)), $script, $a_cmd);
1392 //echo "<br>setReturn:".get_class($a_gui_obj).":".$script.":<br>";
1393  $this->return[strtolower(get_class($a_gui_obj))] = $script;
1394  }
1395 
1399  function setReturnByClass($a_class, $a_cmd)
1400  {
1401  // may not be an array!
1402  $a_class = strtolower($a_class);
1403 
1404  $script = $this->getTargetScript();
1405  $script = $this->getUrlParameters($a_class, $script, $a_cmd);
1406 //echo "<br>setReturn:".get_class($a_gui_obj).":".$script.":<br>";
1407  $this->return[strtolower($a_class)] = $script;
1408  }
1409 
1413  function returnToParent(&$a_gui_obj, $a_anchor = "")
1414  {
1415  $script = $this->getParentReturn($a_gui_obj);
1416 
1417  $script = ilUtil::appendUrlParameterString($script,
1418  "redirectSource=".strtolower(get_class($a_gui_obj)));
1419  $script = ilUtil::appendUrlParameterString($script,
1420  "cmdMode=".$_GET["cmdMode"]);
1421  if ($a_anchor != "")
1422  {
1423  $script = $script."#".$a_anchor;
1424  }
1425 
1426  ilUtil::redirect($script);
1427  }
1428 
1429 
1436  {
1437  return $_GET["redirectSource"];
1438  }
1439 
1443  function getParentReturn(&$a_gui_obj)
1444  {
1445  return $this->getParentReturnByClass(strtolower(get_class($a_gui_obj)));
1446  }
1447 
1448 
1452  function getParentReturnByClass($a_class)
1453  {
1454  $a_class = strtolower($a_class);
1455  $ret_class = $this->searchReturnClass($a_class);
1456 //echo ":$ret_class:";
1457  if($ret_class)
1458  {
1459 //echo ":".$this->return[$ret_class].":";
1460  return $this->return[$ret_class];
1461  }
1462  }
1463 
1470  function getReturnClass($a_class)
1471  {
1472  if (is_object($a_class))
1473  {
1474  $class = strtolower(get_class($a_class));
1475  }
1476  else
1477  {
1478  $class = strtolower($a_class);
1479  }
1480  return $this->searchReturnClass($class);
1481  }
1482 
1483 
1487  private function searchReturnClass($a_class)
1488  {
1489  $a_class = strtolower($a_class);
1490 
1491  $node = $this->getNodeIdForTargetClass($this->current_node, $a_class);
1492  $node = $node["node_id"];
1493  $n_arr = explode(":", $node);
1494  for($i = count($n_arr)-2; $i>=0; $i--)
1495  {
1496  if ($this->return[$this->getClassForCid($n_arr[$i])] != "")
1497  {
1498  return $this->getClassForCid($n_arr[$i]);
1499  }
1500  }
1501 
1502  return false;
1503  }
1504 
1508  public function getUrlParameters($a_class, $a_str, $a_cmd = "", $xml_style = false)
1509  {
1510  // note: $a_class may be an array!
1511  //$a_class = strtolower($a_class);
1512 
1513  $params = $this->getParameterArrayByClass($a_class, $a_cmd);
1514 
1515  foreach ($params as $par => $value)
1516  {
1517  if (strlen((string) $value))
1518  {
1519  $a_str = ilUtil::appendUrlParameterString($a_str, $par."=".$value, $xml_style);
1520  }
1521  }
1522 
1523  return $a_str;
1524  }
1525 
1529  public function getParameterArray(&$a_gui_obj, $a_cmd = "")
1530  {
1531  $par_arr = $this->getParameterArrayByClass(strtolower(get_class($a_gui_obj)), $a_cmd);
1532 
1533  return $par_arr;
1534  }
1535 
1543  public function getParameterArrayByClass($a_class, $a_cmd = "")
1544  {
1545  if ($a_class == "")
1546  {
1547  return array();
1548  }
1549 
1550  if (!is_array($a_class))
1551  {
1552  $a_class = array($a_class);
1553  }
1554 
1555  $nr = $this->current_node;
1556  foreach ($a_class as $class)
1557  {
1558  $class = strtolower($class);
1559  $nr = $this->getNodeIdForTargetClass($nr, $class);
1560  if ($nr["base_class"] != "")
1561  {
1562  $new_baseclass = $nr["base_class"];
1563  }
1564  $nr = $nr["node_id"];
1565  $target_class = $class;
1566  }
1567 
1568  $path = $this->getPathNew(1, $nr);
1569  $params = array();
1570 
1571  // append parameters of parent classes
1572  foreach($path as $node_id)
1573  {
1574  $class = ($node_id == "")
1575  ? strtolower($_GET["baseClass"])
1576  : $this->getClassForCid($this->getCurrentCidOfNode($node_id));
1577  if (isset($this->save_parameter[$class]) && is_array($this->save_parameter[$class]))
1578  {
1579  foreach($this->save_parameter[$class] as $par)
1580  {
1581  if (isset($_GET[$par]))
1582  {
1583  $params[$par] = $_GET[$par];
1584  }
1585  else if (isset($_POST[$par]))
1586  {
1587  $params[$par] = $_POST[$par];
1588  }
1589  }
1590  }
1591 
1592  if (isset($this->parameter[$class]) && is_array($this->parameter[$class]))
1593  {
1594  foreach($this->parameter[$class] as $par => $value)
1595  {
1596  $params[$par] = $value;
1597  }
1598  }
1599  }
1600 
1601  if ($a_cmd != "")
1602  {
1603  $params["cmd"] = $a_cmd;
1604  }
1605 
1606  $params["cmdClass"] = $target_class;
1607  $params["cmdNode"] = $nr;
1608  if($new_baseclass == "")
1609  {
1610  $params["baseClass"] = $_GET["baseClass"];
1611  }
1612  else
1613  {
1614  $params["baseClass"] = $new_baseclass;
1615  }
1616 
1617  return $params;
1618  }
1619 
1623  private function getCidForClass($a_class, $a_check = false)
1624  {
1625  if ($this->class_cid[$a_class] == "")
1626  {
1627  $this->readClassInfo($a_class);
1628  }
1629  if ($this->class_cid[$a_class] == "")
1630  {
1631  if ($a_check)
1632  {
1633  return false;
1634  }
1635  if (DEVMODE == 1)
1636  {
1637  $add = "<br><br>Please make sure your GUI class name ends with 'GUI' and that the filename is 'class.[YourClassName].php'. In exceptional cases you
1638  may solve the issue by putting an empty * @ilCtrl_Calls [YourClassName]: into your class header.".
1639  " In both cases you need to reload the control structure in the setup.";
1640  }
1641  include_once("./Services/UICore/exceptions/class.ilCtrlException.php");
1642  throw new ilCtrlException("Cannot find cid for class ".$a_class.".".$add);
1643  }
1644  return $this->class_cid[$a_class];
1645  }
1646 
1650  private function getClassForCid($a_cid)
1651  {
1652  if ($this->cid_class[$a_cid] == "")
1653  {
1654  $this->readCidInfo($a_cid);
1655  }
1656  if ($this->cid_class[$a_cid] == "")
1657  {
1658  include_once("./Services/UICore/exceptions/class.ilCtrlException.php");
1659  throw new ilCtrlException("Cannot find class for cid ".$a_cid.".");
1660  }
1661  return $this->cid_class[$a_cid];
1662  }
1663 
1669  private function readCidInfo($a_cid)
1670  {
1671  global $ilDB;
1672 
1673  if (isset($this->info_read_cid[$a_cid]))
1674  {
1675  return;
1676  }
1677  $set = $ilDB->query("SELECT * FROM ctrl_classfile ".
1678  " WHERE cid = ".$ilDB->quote($a_cid, "text")
1679  );
1680  if ($rec = $ilDB->fetchAssoc($set))
1681  {
1682  $this->cid_class[$a_cid] = $rec["class"];
1683  $this->class_cid[$rec["class"]] = $a_cid;
1684 
1685  $set = $ilDB->query("SELECT * FROM ctrl_calls ".
1686  " WHERE parent = ".$ilDB->quote($rec["class"], "text")
1687  );
1688  while ($rec2 = $ilDB->fetchAssoc($set))
1689  {
1690  if (!isset($this->calls[$rec["class"]]) || !is_array($this->calls[$rec["class"]]) || !in_array($rec2["child"], $this->calls[$rec["class"]]))
1691  {
1692  if ($rec2["child"] != "")
1693  {
1694  $this->calls[$rec["class"]][] = $rec2["child"];
1695  }
1696  }
1697  }
1698  $this->info_read_class[$rec["class"]] = true;
1699  }
1700 
1701  $this->info_read_cid[$a_cid] = true;
1702  }
1703 
1709  private function readNodeInfo($a_node)
1710  {
1711  $n_arr = explode(":", $a_node);
1712  foreach ($n_arr as $cid)
1713  {
1714  $this->readCidInfo($cid);
1715  }
1716  }
1717 
1723  private function readClassInfo($a_class)
1724  {
1725  global $ilDB;
1726 
1727  $a_class = strtolower($a_class);
1728  if (isset($this->info_read_class[$a_class]))
1729  {
1730  return;
1731  }
1732  $set = $ilDB->query("SELECT * FROM ctrl_classfile ".
1733  " WHERE class = ".$ilDB->quote($a_class, "text")
1734  );
1735  if ($rec = $ilDB->fetchAssoc($set))
1736  {
1737  $this->cid_class[$rec["cid"]] = $a_class;
1738  $this->class_cid[$a_class] = $rec["cid"];
1739  }
1740 
1741  $set = $ilDB->query("SELECT * FROM ctrl_calls ".
1742  " WHERE parent = ".$ilDB->quote($a_class, "text")
1743  );
1744  while ($rec = $ilDB->fetchAssoc($set))
1745  {
1746  if (!isset($this->calls[$a_class]) || !is_array($this->calls[$a_class]) || !in_array($rec["child"], $this->calls[$a_class]))
1747  {
1748  if ($rec["child"] != "")
1749  {
1750  $this->calls[$a_class][] = $rec["child"];
1751  }
1752  }
1753  }
1754 
1755  $this->info_read_class[$a_class] = true;
1756  $this->info_read_cid[$this->class_cid[$a_class]] = true;
1757  }
1758 
1762  private function getParentCidOfNode($a_node)
1763  {
1764  $n_arr = explode(":", $a_node);
1765  return $n_arr[count($n_arr) - 2];
1766  }
1767 
1771  private function removeLastCid($a_node)
1772  {
1773  $lpos = strrpos($a_node, ":");
1774  return substr($a_node, 0, $lpos);
1775  }
1776 
1780  private function getCurrentCidOfNode($a_node)
1781  {
1782  $n_arr = explode(":", $a_node);
1783  return $n_arr[count($n_arr) - 1];
1784  }
1785 
1792  function insertCtrlCalls($a_parent, $a_child, $a_comp_prefix)
1793  {
1794  global $ilDB;
1795 
1796  $a_parent = strtolower($a_parent);
1797  $a_child = strtolower($a_child);
1798  $a_comp_prefix = strtolower($a_comp_prefix);
1799 
1800  $set = $ilDB->query("SELECT * FROM ctrl_calls WHERE ".
1801  " parent = ".$ilDB->quote($a_parent, "text")." AND ".
1802  " child = ".$ilDB->quote($a_child, "text")." AND ".
1803  " comp_prefix = ".$ilDB->quote($a_comp_prefix, "text")
1804  );
1805  if ($rec = $ilDB->fetchAssoc($set))
1806  {
1807  return;
1808  }
1809  $ilDB->manipulate("INSERT INTO ctrl_calls ".
1810  "(parent, child, comp_prefix) VALUES (".
1811  $ilDB->quote($a_parent, "text").",".
1812  $ilDB->quote($a_child, "text").",".
1813  $ilDB->quote($a_comp_prefix, "text").
1814  ")");
1815  }
1816 
1817 }
1818 ?>