ILIAS  Release_5_0_x_branch Revision 61816
 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 require_once('class.ilCachedCtrl.php');
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  $module_class = ilCachedCtrl::getInstance();
98  $mc_rec = $module_class->lookupModuleClass($baseClass);
99  // get class information
100 // $mc_set = $ilDB->query("SELECT * FROM module_class WHERE LOWER(class) = ".
101 // $ilDB->quote($baseClass, "text"));
102 // $mc_rec = $ilDB->fetchAssoc($mc_set);
103 
104  $module = $mc_rec["module"];
105  $class = $mc_rec["class"];
106  $class_dir = $mc_rec["dir"];
107 
108  if ($module != "")
109  {
110  $m_set = $ilDB->query("SELECT * FROM il_component WHERE name = ".
111  $ilDB->quote($module, "text"));
112  $m_rec = $ilDB->fetchAssoc($m_set);
113  $this->module_dir = $m_rec["type"]."/".$m_rec["name"];
114  include_once $this->module_dir."/".$class_dir."/class.".$class.".php";
115  }
116  else // check whether class belongs to a service
117  {
118 // $mc_set = $ilDB->query("SELECT * FROM service_class WHERE LOWER(class) = ".
119 // $ilDB->quote($baseClass, "text"));
120 // $mc_rec = $ilDB->fetchAssoc($mc_set);
121 
122  $mc_rec = $module_class->lookupServiceClass($baseClass);
123 
124  $service = $mc_rec["service"];
125  $class = $mc_rec["class"];
126  $class_dir = $mc_rec["dir"];
127 
128  if ($service == "")
129  {
130  include_once("./Services/UICore/exceptions/class.ilCtrlException.php");
131  throw new ilCtrlException("Could not find entry in modules.xml or services.xml for ".
132  $baseClass." <br/>".str_replace("&", "<br />&", htmlentities($_SERVER["REQUEST_URI"])));
133  }
134 
135  // get service information
136 // $m_set = $ilDB->query("SELECT * FROM il_component WHERE name = ".
137 // $ilDB->quote($service, "text"));
138 // $m_rec = $ilDB->fetchAssoc($m_set);
139 
140  $m_rec = ilComponent::getComponentInfo('Services', $service);
141 
142  $this->service_dir = $m_rec["type"]."/".$m_rec["name"];
143 
144  include_once $this->service_dir."/".$class_dir."/class.".$class.".php";;
145  }
146 
147  // forward processing to base class
148  $this->getCallStructure(strtolower($baseClass));
149  $base_class_gui =& new $class();
150  $this->forwardCommand($base_class_gui);
151  }
152 
156  function getModuleDir()
157  {
158  return $this->module_dir;
159  }
160 
170  function &forwardCommand(&$a_gui_object)
171  {
172  $class = strtolower(get_class($a_gui_object));
173 //echo "<br>class:".$class.":";
174  $nr = $this->getNodeIdForTargetClass($this->current_node, $class);
175  $nr = $nr["node_id"];
176  if ($nr != "")
177  {
178  $current_node = $this->current_node;
179 
180  $this->current_node = $nr;
181 
182  // always populate the call history
183  // it will only be displayed in DEVMODE but is needed for UI plugins, too
184  $this->call_hist[] = array("class" => get_class($a_gui_object),
185  "mode" => "execComm", "cmd" => $this->getCmd());
186 
187 //echo "<br>class:".get_class($a_gui_object).":";
188  $html = $a_gui_object->executeCommand();
189 
190  // reset current node
191  $this->current_node = $current_node;
192 
193  return $html;
194 
195  }
196 
197  include_once("./Services/UICore/exceptions/class.ilCtrlException.php");
198  throw new ilCtrlException("ERROR: Can't forward to class $class.");
199  }
200 
208  function &getHTML(&$a_gui_object)
209  {
210  $class = strtolower(get_class($a_gui_object));
211 
212  $nr = $this->getNodeIdForTargetClass($this->current_node, $class);
213  $nr = $nr["node_id"];
214  if ($nr != "")
215  {
216  $current_node = $this->current_node;
217 
218  // set current node to new gui class
219  $this->current_node = $nr;
220 
221  // always populate the call history
222  // it will only be displayed in DEVMODE but is needed for UI plugins, too
223  $this->call_hist[] = array("class" => get_class($a_gui_object),
224  "mode" => "getHtml", "cmd" => $this->getCmd());
225 
226  // get block
227  $html = $a_gui_object->getHTML();
228 
229  // reset current node
230  $this->current_node = $current_node;
231 
232  // return block
233  return $html;
234  }
235 
236  include_once("./Services/UICore/exceptions/class.ilCtrlException.php");
237  throw new ilCtrlException("ERROR: Can't getHTML from class $class.");
238 
239  }
240 
250  function setContext($a_obj_id, $a_obj_type, $a_sub_obj_id = 0, $a_sub_obj_type = "")
251  {
252  $this->context_obj_id = $a_obj_id;
253  $this->context_obj_type = $a_obj_type;
254  $this->context_sub_obj_id = $a_sub_obj_id;
255  $this->context_sub_obj_type = $a_sub_obj_type;
256  }
257 
263  public function getContextObjId()
264  {
265  return $this->context_obj_id;
266  }
267 
273  public function getContextObjType()
274  {
275  return $this->context_obj_type;
276  }
277 
283  public function getContextSubObjId()
284  {
285  return $this->context_sub_obj_id;
286  }
287 
293  public function getContextSubObjType()
294  {
295  return $this->context_sub_obj_type;
296  }
297 
316  private function getNodeIdForTargetClass($a_par_node, $a_class, $a_check = false)
317  {
318  $class = strtolower($a_class);
319  $this->readClassInfo($class);
320 
321  if ($a_par_node === 0 || $a_par_node == "")
322  {
323  return array("node_id" => $this->getCidForClass($class),
324  "base_class" => "");
325  }
326 
327  $this->readNodeInfo($a_par_node);
328 
329  $node_cid = $this->getCurrentCidOfNode($a_par_node);
330 
331  // target class is class of current node id
332  if ($class == $this->getClassForCid($node_cid))
333  {
334  return array("node_id" => $a_par_node,
335  "base_class" => "");
336  }
337 
338  // target class is child of current node id
339  if (isset($this->calls[$this->getClassForCid($node_cid)]) &&
340  is_array($this->calls[$this->getClassForCid($node_cid)]) &&
341  in_array($a_class, $this->calls[$this->getClassForCid($node_cid)]))
342  {
343  return array("node_id" => $a_par_node.":".$this->getCidForClass($class),
344  "base_class" => "");
345  }
346 
347  // target class is sibling
348  $par_cid = $this->getParentCidOfNode($a_par_node);
349  if ($par_cid != "")
350  {
351  if (is_array($this->calls[$this->getClassForCid($par_cid)]) &&
352  in_array($a_class, $this->calls[$this->getClassForCid($par_cid)]))
353  {
354  return array("node_id" =>
355  $this->removeLastCid($a_par_node).":".$this->getCidForClass($class),
356  "base_class" => "");
357  }
358  }
359 
360  // target class is parent
361  $temp_node = $this->removeLastCid($a_par_node);
362  while($temp_node != "")
363  {
364  $temp_cid = $this->getCurrentCidOfNode($temp_node);
365  if ($this->getClassForCid($temp_cid) == $a_class)
366  {
367  return array("node_id" => $temp_node,
368  "base_class" => "");
369  }
370  $temp_node = $this->removeLastCid($temp_node);
371  }
372 
373  // target class is another base class
374  $n_class = "";
375  if ($a_class != "")
376  {
377  $module_class = ilCachedCtrl::getInstance();
378  $mc_rec = $module_class->lookupModuleClass($class);
379  $n_class = $mc_rec['lower_class'];
380 // global $ilDB;
381 //
382 // get class information
383 // $mc_set = $ilDB->query("SELECT * FROM module_class WHERE LOWER(class) = ".
384 // $ilDB->quote($class, "text"));
385 // $mc_rec = $ilDB->fetchAssoc($mc_set);
386 // $n_class = strtolower($mc_rec["class"]);
387 
388  if ($n_class == "")
389  {
390  $mc_rec = $module_class->lookupServiceClass($class);
391  $n_class = $mc_rec['lower_class'];
392 
393 // $mc_set = $ilDB->query("SELECT * FROM service_class WHERE LOWER(class) = ".
394 // $ilDB->quote($class, "text"));
395 // $mc_rec = $ilDB->fetchAssoc($mc_set);
396 // $n_class = strtolower($mc_rec["class"]);
397 
398  }
399 
400  if ($n_class != "")
401  {
402  $this->getCallStructure($n_class);
403  return array("node_id" => $this->getCidForClass($n_class),
404  "base_class" => $class);
405  }
406  }
407 
408  if ($a_check)
409  {
410  return false;
411  }
412 
413  // Please do NOT change these lines.
414  // Developers must be aware, if they use classes unknown to the controller
415  // otherwise certain problem will be extremely hard to track down...
416 
417 // echo "ERROR: Can't find target class $a_class for node $a_par_node ".
418 // "(".$this->cid_class[$this->getParentCidOfNode($a_par_node)].").<br>";
419  error_log( "ERROR: Can't find target class $a_class for node $a_par_node ".
420  "(".$this->cid_class[$this->getParentCidOfNode($a_par_node)].")");
421 
422  if (DEVMODE == 1)
423  {
424 // ilUtil::printBacktrace();
425  }
426 
427  include_once("./Services/UICore/exceptions/class.ilCtrlException.php");
428  throw new ilCtrlException("ERROR: Can't find target class $a_class for node $a_par_node ".
429  "(".$this->cid_class[$this->getParentCidOfNode($a_par_node)].").");
430  }
431 
438  function checkTargetClass($a_class)
439  {
440  if (!is_array($a_class))
441  {
442  $a_class = array($a_class);
443  }
444 
445  $nr = $this->current_node;
446  foreach ($a_class as $class)
447  {
448  $class = strtolower($class);
449 
450  if (!$this->getCidForClass($class, true))
451  {
452  return false;
453  }
454 
455  $nr = $this->getNodeIdForTargetClass($nr, $class, true);
456  $nr = $nr["node_id"];
457  if ($nr === false)
458  {
459  return false;
460  }
461  }
462  return true;
463  }
464 
470  function getCmdNode()
471  {
472  return $_GET["cmdNode"];
473  }
474 
482  function addLocation($a_title, $a_link, $a_target = "", $a_ref_id = 0)
483  {
484  $this->location[] = array("title" => $a_title,
485  "link" => $a_link, "target" => $a_target, "ref_id" => $a_ref_id);
486  }
487 
493  function getLocations()
494  {
495  return $this->location;
496  }
497 
506  function addTab($a_lang_var, $a_link, $a_cmd, $a_class)
507  {
508  $a_class = strtolower($a_class);
509 
510  $this->tab[] = array("lang_var" => $a_lang_var,
511  "link" => $a_link, "cmd" => $a_cmd, "class" => $a_class);
512  }
513 
519  function getTabs()
520  {
521  return $this->tab;
522  }
523 
530  function getCallHistory()
531  {
532  return $this->call_hist;
533  }
534 
551  function getCallStructure($a_class)
552  {
553  $this->readClassInfo($a_class);
554  }
555 
560 /* function storeCommonStructures()
561  {
562  global $ilDB;
563 
564  $ilDB->manipulate("DELETE FROM ctrl_structure");
565 
566  foreach ($this->stored_trees as $root_gui_class)
567  {
568  $this->call_node = array();
569  $this->forward = array();
570  $this->parent = array();
571  $this->readCallStructure($root_gui_class);
572  $ilDB->insert("ctrl_structure", array(
573  "root_class" => array("text", $root_gui_class),
574  "call_node" => array("text", serialize($this->call_node)),
575  "forward" => array("text", serialize($this->forward)),
576  "parent" => array("clob", serialize($this->parent))));
577  }
578  }
579 */
580 
584  function readCallStructure($a_class, $a_nr = 0, $a_parent = 0)
585  {
586  global $ilDB;
587 
588  $a_class = strtolower($a_class);
589 
590  $a_nr++;
591 
592  // determine call node structure
593  $this->call_node[$a_nr] = array("class" => $a_class, "parent" => $a_parent);
594 
595 //echo "<br>nr:$a_nr:class:$a_class:parent:$a_parent:";
596  $call_set = $ilDB->query("SELECT * FROM ctrl_calls WHERE parent = ".
597  $ilDB->quote(strtolower($a_class), "text").
598  " ORDER BY child", array("text"));
599  $a_parent = $a_nr;
600  while ($call_rec = $ilDB->fetchAssoc($call_set))
601  {
602  $a_nr = $this->readCallStructure($call_rec["child"], $a_nr, $a_parent);
603  $forw[] = $call_rec["child"];
604  }
605 
606  // determin forward and parent array
607  $this->forwards($a_class, $forw);
608 //echo "<br>forwards:".$a_class."<br>"; var_dump($forw);
609 
610  // determine root class
611  $this->root_class = $a_class;
612  return $a_nr;
613  }
614 
615 
622  private function forwards($a_from_class, $a_to_class)
623  {
624  $a_from_class = strtolower($a_from_class);
625 
626  if (is_array($a_to_class))
627  {
628  foreach($a_to_class as $to_class)
629  {
630  if ($a_from_class != "" && $to_class != "")
631  {
632  if (!is_array($this->forward[$a_from_class]) || !in_array(strtolower($to_class), $this->forward[$a_from_class]))
633  {
634  $this->forward[$a_from_class][] = strtolower($to_class);
635  }
636  if (!is_array($this->parent[strtolower($to_class)]) || !in_array($a_from_class, $this->parent[strtolower($to_class)]))
637  {
638  $this->parent[strtolower($to_class)][] = $a_from_class;
639  }
640  }
641  }
642  }
643  else
644  {
645  $to_class = $a_to_class;
646  if ($a_from_class != "" && $to_class != "")
647  {
648  if (!is_array($this->forward[$a_from_class]) || !in_array(strtolower($to_class), $this->forward[$a_from_class]))
649  {
650  $this->forward[$a_from_class][] = strtolower($to_class);
651  }
652  if (!is_array($this->parent[strtolower($to_class)]) || !in_array($a_from_class, $this->parent[strtolower($to_class)]))
653  {
654  $this->parent[strtolower($to_class)][] = $a_from_class;
655  }
656  }
657  }
658  }
659 
660 
680  public function saveParameter(&$a_obj, $a_parameter)
681  {
682  if (is_object($a_obj))
683  {
684  $this->saveParameterByClass(get_class($a_obj), $a_parameter);
685  }
686  }
687 
694  function saveParameterByClass($a_class, $a_parameter)
695  {
696  if (is_array($a_parameter))
697  {
698  foreach($a_parameter as $parameter)
699  {
700  $this->save_parameter[strtolower($a_class)][] = $parameter;
701  }
702  }
703  else
704  {
705  $this->save_parameter[strtolower($a_class)][] = $a_parameter;
706  }
707  }
708 
709 
732  public function setParameter(&$a_obj, $a_parameter, $a_value)
733  {
734  $this->parameter[strtolower(get_class($a_obj))][$a_parameter] = $a_value;
735  }
736 
737 
745  public function setParameterByClass($a_class, $a_parameter, $a_value)
746  {
747  $this->parameter[strtolower($a_class)][$a_parameter] = $a_value;
748  }
749 
750 
757  public function clearParameters(&$a_obj)
758  {
759  $this->clearParametersByClass(strtolower(get_class($a_obj)));
760  }
761 
768  public function clearParametersByClass($a_class)
769  {
770  $this->parameter[strtolower($a_class)] = array();
771  }
772 
781  function getNextClass()
782  {
783  $cmdNode = $this->getCmdNode();
784 //echo "<br>getNextClass (current node: ".$this->current_node."; cmd node: ".$cmdNode.") ";
785  if ($cmdNode == "")
786  {
787  return false;
788  }
789  else
790  {
791  if ($this->current_node == $cmdNode)
792  {
793 //echo "1:".$this->call_node[$cmdNode]["class"]."<br>";
794  //return $this->call_node[$cmdNode]["class"];
795  return "";
796  }
797  else
798  {
799  $path = $this->getPathNew($this->current_node, $cmdNode);
800 //var_dump($path);
801 //echo " - Next Node: ".$path[1];
802  $this->readCidInfo($this->getCurrentCidOfNode($path[1]));
803 //echo ":".$this->cid_class[$this->getCurrentCidOfNode($path[1])].":".$this->getCurrentCidOfNode($path[1]).":";
804  return $this->cid_class[$this->getCurrentCidOfNode($path[1])];
805  }
806  }
807  }
808 
815  function lookupClassPath($a_class_name)
816  {
817  global $ilDB;
818  $a_class_name = strtolower($a_class_name);
819 
820  $cached_ctrl = ilCachedCtrl::getInstance();
821  $class_rec = $cached_ctrl->lookupClassFile($a_class_name);
822 
823  //$class_set = $ilDB->query("SELECT * FROM ctrl_classfile WHERE class = ".
824  // $ilDB->quote($a_class_name, "text"));
825  //$class_rec = $ilDB->fetchAssoc($class_set);
826 
827  if ($class_rec["plugin_path"] != "")
828  {
829  return $class_rec["plugin_path"]."/".$class_rec["filename"];
830  }
831  else
832  {
833  return $class_rec["filename"];
834  }
835  }
836 
845  function getClassForClasspath($a_class_path)
846  {
847  $path = pathinfo($a_class_path);
848  $file = $path["basename"];
849  $class = substr($file, 6, strlen($file) - 10);
850 
851  return $class;
852  }
853 
860  private function getPathNew($a_source_node, $a_target_node)
861  {
862 //if ($this->getCmdClass() == "ilmailfoldergui") echo "-".$a_source_node."-".$a_target_node."-";
863 //echo "-".$a_source_node."-".$a_target_node."-";
864 //echo "<br>:::$a_source_node:::";
865  if ($a_source_node == "1")
866  {
867  $a_source_node = "";
868  }
869  if (substr($a_target_node, 0, strlen($a_source_node)) != $a_source_node)
870  {
871  $failure = "ERROR: Path not found. Source:".$a_source_node.
872  ", Target:".$a_target_node;
873  if (DEVMODE == 1)
874  {
875  include_once("./Services/UICore/exceptions/class.ilCtrlException.php");
876  throw new ilCtrlException($failure);
877  }
878  $GLOBALS['ilLog']->write(__METHOD__.' '.$failure);
879  ilUtil::redirect('./ilias.php?baseClass=ilRepositoryGUI');
880  }
881 //echo "<br>:::$a_source_node:::";
882  $temp_node = $a_source_node;
883 
884  $path = array();
885  if ($a_source_node != "")
886  {
887  $path = array($a_source_node);
888  }
889 
890  $diffstart = ($a_source_node == "")
891  ? 0
892  : strlen($a_source_node) + 1;
893  $diff = substr($a_target_node, $diffstart);
894 //echo "=$diff=$diffstart=";
895  $diff_arr = explode(":", $diff);
896  foreach($diff_arr as $cid)
897  {
898  if ($temp_node != "")
899  {
900  $temp_node.= ":";
901  }
902  $temp_node.= $cid;
903  $path[] = $temp_node;
904  }
905 //if ($this->getCmdClass() == "ilmailfoldergui") var_dump($path);
906 //var_dump($path);
907  return $path;
908  }
909 
915  public function setTargetScript($a_target_script)
916  {
917  $this->target_script = $a_target_script;
918  }
919 
920 
926  public function getTargetScript()
927  {
928  return $this->target_script;
929  }
930 
931 
940  public function initBaseClass($a_base_class)
941  {
942  $_GET["baseClass"] = $a_base_class;
943  $_GET["cmd"] = "";
944  $_GET["cmdClass"] = "";
945  $_GET["cmdNode"] = "";
946  $this->init();
947  }
948 
956  public function getCmd($a_default_cmd = "", $a_safe_commands = "")
957  {
958  $cmd = "";
959  if (isset($_GET["cmd"]))
960  {
961  $cmd = $_GET["cmd"];
962  }
963  if($cmd == "post")
964  {
965  if (isset($_POST["cmd"]) && is_array($_POST["cmd"]))
966  {
967  reset($_POST["cmd"]);
968  }
969  $cmd = @key($_POST["cmd"]);
970 
971  // verify command
972  if ($this->verified_cmd != "")
973  {
974  return $this->verified_cmd;
975  }
976  else
977  {
978  if (!$this->verifyToken() &&
979  (!is_array($a_safe_commands) || !in_array($cmd, $a_safe_commands)))
980  {
981  return $a_default_cmd;
982  }
983  }
984 
985  $this->verified_cmd = $cmd;
986  if($cmd == "" && isset($_POST["table_top_cmd"])) // selected command in multi-list (table2)
987  {
988  $cmd = @key($_POST["table_top_cmd"]);
989  $this->verified_cmd = $cmd;
990  $_POST[$_POST["cmd_sv"][$cmd]] = $_POST[$_POST["cmd_sv"][$cmd]."_2"];
991  }
992  if($cmd == "" && isset($_POST["select_cmd2"])) // selected command in multi-list (table2)
993  {
994  if(isset($_POST["select_cmd_all2"]))
995  {
996  $_POST["select_cmd_all"] = $_POST["select_cmd_all2"];
997  }
998  else
999  {
1000  $_POST["select_cmd_all"] = $_POST["select_cmd_all2"] = null;
1001  }
1002  $cmd = $_POST["selected_cmd2"];
1003  $this->verified_cmd = $cmd;
1004  }
1005  if($cmd == "" && isset($_POST["select_cmd"])) // selected command in multi-list (table2)
1006  {
1007  if(isset($_POST["select_cmd_all"]))
1008  {
1009  $_POST["select_cmd_all2"] = $_POST["select_cmd_all"];
1010  }
1011  else
1012  {
1013  $_POST["select_cmd_all"] = $_POST["select_cmd_all2"] = null;
1014  }
1015  $cmd = $_POST["selected_cmd"];
1016  $this->verified_cmd = $cmd;
1017  }
1018  if($cmd == "")
1019  {
1020  $cmd = $_GET["fallbackCmd"];
1021  $this->verified_cmd = $cmd;
1022  }
1023  }
1024  if($cmd == "")
1025  {
1026  $cmd = $a_default_cmd;
1027  }
1028  return $cmd;
1029  }
1030 
1041  function setCmd($a_cmd)
1042  {
1043  $_GET["cmd"] = $a_cmd;
1044  }
1045 
1056  public function setCmdClass($a_cmd_class)
1057  {
1058  $a_cmd_class = strtolower($a_cmd_class);
1059  $nr = $this->getNodeIdForTargetClass($this->current_node, $a_cmd_class);
1060  $nr = $nr["node_id"];
1061  $_GET["cmdClass"] = $a_cmd_class;
1062  $_GET["cmdNode"] = $nr;
1063  }
1064 
1070  function getCmdClass()
1071  {
1072  return strtolower($_GET["cmdClass"]);
1073  }
1074 
1085  function getFormAction(&$a_gui_obj, $a_fallback_cmd = "", $a_anchor = "", $a_asynch = false,
1086  $xml_style = true)
1087  {
1088  $script = $this->getFormActionByClass(strtolower(get_class($a_gui_obj)),
1089  $a_fallback_cmd, $a_anchor, $a_asynch, $xml_style);
1090  return $script;
1091  }
1092 
1103  function getFormActionByClass($a_class, $a_fallback_cmd = "", $a_anchor = "", $a_asynch = false,
1104  $xml_style = true)
1105  {
1106  if(!is_array($a_class))
1107  {
1108  $a_class = strtolower($a_class);
1109  }
1110 
1111  $tok = $this->getRequestToken();
1112 
1113  if ($a_asynch)
1114  {
1115  $xml_style = false;
1116  }
1117 
1118  $script = $this->getLinkTargetByClass($a_class, "post", "", $a_asynch);
1119  if ($a_fallback_cmd != "")
1120  {
1121  $script = ilUtil::appendUrlParameterString($script, "fallbackCmd=".$a_fallback_cmd, $xml_style);
1122  }
1123  $script = ilUtil::appendUrlParameterString($script, self::IL_RTOKEN_NAME.'='.$this->getRequestToken(),
1124  $xml_style);
1125  if ($a_anchor != "")
1126  {
1127  $script = $script."#".$a_anchor;
1128  }
1129 
1130  return $script;
1131  }
1132 
1139  public function appendRequestTokenParameterString($a_url, $xml_style = true)
1140  {
1141  return ilUtil::appendUrlParameterString($a_url, self::IL_RTOKEN_NAME.'='.$this->getRequestToken(),
1142  $xml_style);
1143  }
1144 
1150  public function getRequestToken()
1151  {
1152  global $ilDB, $ilUser;
1153 
1154  if ($this->rtoken != "")
1155  {
1156  return $this->rtoken;
1157  }
1158  else
1159  {
1160  if (is_object($ilDB) && is_object($ilUser) && $ilUser->getId() > 0 &&
1161  $ilUser->getId() != ANONYMOUS_USER_ID)
1162  {
1163  $res = $ilDB->query("SELECT token FROM il_request_token WHERE user_id = ".
1164  $ilDB->quote($ilUser->getId(), "integer").
1165  " AND session_id = ".$ilDB->quote(session_id(), "text"));
1166  $rec = $ilDB->fetchAssoc($res);
1167 //echo session_id();
1168  if ($rec["token"] != "")
1169  {
1170  $this->rtoken = $rec["token"];
1171  return $rec["token"];
1172  }
1173 //echo "new rtoken, new entry for :".$ilUser->getId().":".session_id().":"; exit;
1174  $this->rtoken = md5(uniqid(rand(), true));
1175 
1176  // delete entries older than one and a half days
1177  if (rand(1, 200) == 2)
1178  {
1179  $dt = new ilDateTime(time(),IL_CAL_UNIX);
1180  $dt->increment(IL_CAL_DAY, -1);
1181  $dt->increment(IL_CAL_HOUR, -12);
1182  $dq = "DELETE FROM il_request_token WHERE ".
1183  " stamp < ".$ilDB->quote($dt->get(IL_CAL_DATETIME), "timestamp");
1184  $ilDB->manipulate($dq);
1185  }
1186 
1187  // IMPORTANT: Please do NOT try to move this implementation to a
1188  // session basis. This will fail due to framesets that are used
1189  // occasionally in ILIAS, e.g. in the chat, where multiple
1190  // forms are loaded in different frames.
1191  $ilDB->manipulate("INSERT INTO il_request_token (user_id, token, stamp, session_id) VALUES ".
1192  "(".
1193  $ilDB->quote($ilUser->getId(), "integer").",".
1194  $ilDB->quote($this->rtoken, "text").",".
1195  $ilDB->now().",".
1196  $ilDB->quote(session_id(), "text").")");
1197  return $this->rtoken;
1198  }
1199  //$this->rtoken = md5(uniqid(rand(), true));
1200  }
1201  return "";
1202  }
1203 
1209  private function verifyToken()
1210  {
1211  global $ilDB, $ilUser;
1212 
1213  if (is_object($ilUser) && is_object($ilDB) && $ilUser->getId() > 0 &&
1214  $ilUser->getId() != ANONYMOUS_USER_ID)
1215  {
1216  if ($_GET["rtoken"] == "")
1217  {
1218  #echo "ilCtrl::No Request Token Given!"; // for debugging, maybe changed later
1219  return false;
1220  }
1221 
1222  $set = $ilDB->query("SELECT * FROM il_request_token WHERE ".
1223  " user_id = ".$ilDB->quote($ilUser->getId(), "integer")." AND ".
1224  " token = ".$ilDB->quote($_GET[self::IL_RTOKEN_NAME]), "text");
1225  if ($ilDB->numRows($set) > 0)
1226  {
1227  // remove used token
1228  /*
1229  $ilDB->query("DELETE FROM il_request_token WHERE ".
1230  " user_id = ".$ilDB->quote($ilUser->getId())." AND ".
1231  " token = ".$ilDB->quote($_GET[self::IL_RTOKEN_NAME]));
1232  */
1233 
1234  // remove tokens from older sessions
1235  // if we do this immediately, working with multiple windows does not work:
1236  // - window one: open form (with token a)
1237  // - window two: open form (with token b)
1238  // - submit window one: a is verified, but b must not be deleted immediately, otherwise
1239  // - window two: submit results in invalid token
1240  // see also bug #13551
1241  $dt = new ilDateTime(time(),IL_CAL_UNIX);
1242  $dt->increment(IL_CAL_DAY, -1);
1243  $dt->increment(IL_CAL_HOUR, -12);
1244  $ilDB->manipulate("DELETE FROM il_request_token WHERE ".
1245  " user_id = ".$ilDB->quote($ilUser->getId(), "integer")." AND ".
1246  " session_id != ".$ilDB->quote(session_id(), "text")." AND ".
1247  " stamp < ".$ilDB->quote($dt->get(IL_CAL_DATETIME), "timestamp"));
1248  return true;
1249  }
1250  else
1251  {
1252  return false;
1253  }
1254 
1255  if ($_SESSION["rtokens"][$_GET[self::IL_RTOKEN_NAME]] != "")
1256  {
1257  // remove used token
1258  unset($_SESSION["rtokens"][$_GET[self::IL_RTOKEN_NAME]]);
1259 
1260  // remove old tokens
1261  if (count($_SESSION["rtokens"]) > 100)
1262  {
1263  $to_remove = array();
1264  $sec = 7200; // two hours
1265 
1266  foreach($_SESSION["rtokens"] as $tok => $time)
1267  {
1268  if (time() - $time > $sec)
1269  {
1270  $to_remove[] = $tok;
1271  }
1272  }
1273  foreach($to_remove as $tok)
1274  {
1275  unset($_SESSION["rtokens"][$tok]);
1276  }
1277  }
1278 
1279  return true;
1280  }
1281  return false;
1282  }
1283  else
1284  {
1285  return true; // do not verify, if user or db object is missing
1286  }
1287 
1288  return false;
1289  }
1290 
1298  public function redirect(&$a_gui_obj, $a_cmd = "", $a_anchor = "", $a_asynch = false)
1299  {
1300  global $ilBench;
1301 
1302  $script = $this->getLinkTargetByClass(strtolower(get_class($a_gui_obj)), $a_cmd,
1303  "", $a_asynch, false);
1304  if (is_object($ilBench))
1305  {
1306  $ilBench->save();
1307  }
1308  if ($a_anchor != "")
1309  {
1310  $script = $script."#".$a_anchor;
1311  }
1312  ilUtil::redirect($script);
1313  }
1314 
1315 
1322  public function redirectByClass($a_class, $a_cmd = "", $a_anchor = "", $a_asynch = false)
1323  {
1324  $script = $this->getLinkTargetByClass($a_class, $a_cmd, "", $a_asynch, false);
1325  if ($a_anchor != "")
1326  {
1327  $script = $script."#".$a_anchor;
1328  }
1329  ilUtil::redirect($script);
1330  }
1331 
1337  public function isAsynch()
1338  {
1339  if (isset($_GET["cmdMode"]) && $_GET["cmdMode"] == "asynch")
1340  {
1341  return true;
1342  }
1343  else
1344  {
1345  return false;
1346  }
1347  }
1348 
1349 
1361  function getLinkTarget(&$a_gui_obj, $a_cmd = "", $a_anchor = "", $a_asynch = false,
1362  $xml_style = true)
1363  {
1364  $script = $this->getLinkTargetByClass(strtolower(get_class($a_gui_obj)), $a_cmd, $a_anchor, $a_asynch,
1365  $xml_style);
1366  return $script;
1367  }
1368 
1369 
1381  function getLinkTargetByClass($a_class, $a_cmd = "", $a_anchor = "", $a_asynch = false,
1382  $xml_style = true)
1383  {
1384  if ($a_asynch)
1385  {
1386  $xml_style = false;
1387  }
1388 
1389  // note: $a_class may be an array
1390  //$a_class = strtolower($a_class);
1391 
1392 //echo "<br>getLinkTargetByClass";
1393  $script = $this->getTargetScript();
1394  $script = $this->getUrlParameters($a_class, $script, $a_cmd, $xml_style);
1395 
1396  if ($a_asynch)
1397  {
1398  //$amp = $xml_style
1399  // ? "&amp;"
1400  // : "&";
1401  $amp = "&";
1402  $script.= $amp."cmdMode=asynch";
1403  }
1404 
1405  if ($a_anchor != "")
1406  {
1407  $script = $script."#".$a_anchor;
1408  }
1409 
1410  return $script;
1411  }
1412 
1416  function setReturn(&$a_gui_obj, $a_cmd)
1417  {
1418  $script = $this->getTargetScript();
1419  $script = $this->getUrlParameters(strtolower(get_class($a_gui_obj)), $script, $a_cmd);
1420 //echo "<br>setReturn:".get_class($a_gui_obj).":".$script.":<br>";
1421  $this->return[strtolower(get_class($a_gui_obj))] = $script;
1422  }
1423 
1427  function setReturnByClass($a_class, $a_cmd)
1428  {
1429  // may not be an array!
1430  $a_class = strtolower($a_class);
1431 
1432  $script = $this->getTargetScript();
1433  $script = $this->getUrlParameters($a_class, $script, $a_cmd);
1434 //echo "<br>setReturn:".get_class($a_gui_obj).":".$script.":<br>";
1435  $this->return[strtolower($a_class)] = $script;
1436  }
1437 
1441  function returnToParent(&$a_gui_obj, $a_anchor = "")
1442  {
1443  $script = $this->getParentReturn($a_gui_obj);
1444 
1445  $script = ilUtil::appendUrlParameterString($script,
1446  "redirectSource=".strtolower(get_class($a_gui_obj)));
1447  $script = ilUtil::appendUrlParameterString($script,
1448  "cmdMode=".$_GET["cmdMode"]);
1449  if ($a_anchor != "")
1450  {
1451  $script = $script."#".$a_anchor;
1452  }
1453 
1454  ilUtil::redirect($script);
1455  }
1456 
1457 
1464  {
1465  return $_GET["redirectSource"];
1466  }
1467 
1471  function getParentReturn(&$a_gui_obj)
1472  {
1473  return $this->getParentReturnByClass(strtolower(get_class($a_gui_obj)));
1474  }
1475 
1476 
1480  function getParentReturnByClass($a_class)
1481  {
1482  $a_class = strtolower($a_class);
1483  $ret_class = $this->searchReturnClass($a_class);
1484 //echo ":$ret_class:";
1485  if($ret_class)
1486  {
1487 //echo ":".$this->return[$ret_class].":";
1488  return $this->return[$ret_class];
1489  }
1490  }
1491 
1498  function getReturnClass($a_class)
1499  {
1500  if (is_object($a_class))
1501  {
1502  $class = strtolower(get_class($a_class));
1503  }
1504  else
1505  {
1506  $class = strtolower($a_class);
1507  }
1508  return $this->searchReturnClass($class);
1509  }
1510 
1511 
1515  private function searchReturnClass($a_class)
1516  {
1517  $a_class = strtolower($a_class);
1518 
1519  $node = $this->getNodeIdForTargetClass($this->current_node, $a_class);
1520  $node = $node["node_id"];
1521  $n_arr = explode(":", $node);
1522  for($i = count($n_arr)-2; $i>=0; $i--)
1523  {
1524  if ($this->return[$this->getClassForCid($n_arr[$i])] != "")
1525  {
1526  return $this->getClassForCid($n_arr[$i]);
1527  }
1528  }
1529 
1530  return false;
1531  }
1532 
1536  public function getUrlParameters($a_class, $a_str, $a_cmd = "", $xml_style = false)
1537  {
1538  // note: $a_class may be an array!
1539  //$a_class = strtolower($a_class);
1540 
1541  $params = $this->getParameterArrayByClass($a_class, $a_cmd);
1542 
1543  foreach ($params as $par => $value)
1544  {
1545  if (strlen((string) $value))
1546  {
1547  $a_str = ilUtil::appendUrlParameterString($a_str, $par."=".$value, $xml_style);
1548  }
1549  }
1550 
1551  return $a_str;
1552  }
1553 
1557  public function getParameterArray(&$a_gui_obj, $a_cmd = "")
1558  {
1559  $par_arr = $this->getParameterArrayByClass(strtolower(get_class($a_gui_obj)), $a_cmd);
1560 
1561  return $par_arr;
1562  }
1563 
1571  public function getParameterArrayByClass($a_class, $a_cmd = "")
1572  {
1573  if ($a_class == "")
1574  {
1575  return array();
1576  }
1577 
1578  if (!is_array($a_class))
1579  {
1580  $a_class = array($a_class);
1581  }
1582 
1583  $nr = $this->current_node;
1584  foreach ($a_class as $class)
1585  {
1586  $class = strtolower($class);
1587  $nr = $this->getNodeIdForTargetClass($nr, $class);
1588  if ($nr["base_class"] != "")
1589  {
1590  $new_baseclass = $nr["base_class"];
1591  }
1592  $nr = $nr["node_id"];
1593  $target_class = $class;
1594  }
1595 
1596  $path = $this->getPathNew(1, $nr);
1597  $params = array();
1598 
1599  // append parameters of parent classes
1600  foreach($path as $node_id)
1601  {
1602  $class = ($node_id == "")
1603  ? strtolower($_GET["baseClass"])
1604  : $this->getClassForCid($this->getCurrentCidOfNode($node_id));
1605  if (isset($this->save_parameter[$class]) && is_array($this->save_parameter[$class]))
1606  {
1607  foreach($this->save_parameter[$class] as $par)
1608  {
1609  if (isset($_GET[$par]))
1610  {
1611  $params[$par] = $_GET[$par];
1612  }
1613  else if (isset($_POST[$par]))
1614  {
1615  $params[$par] = $_POST[$par];
1616  }
1617  }
1618  }
1619 
1620  if (isset($this->parameter[$class]) && is_array($this->parameter[$class]))
1621  {
1622  foreach($this->parameter[$class] as $par => $value)
1623  {
1624  $params[$par] = $value;
1625  }
1626  }
1627  }
1628 
1629  if ($a_cmd != "")
1630  {
1631  $params["cmd"] = $a_cmd;
1632  }
1633 
1634  $params["cmdClass"] = $target_class;
1635  $params["cmdNode"] = $nr;
1636  if($new_baseclass == "")
1637  {
1638  $params["baseClass"] = $_GET["baseClass"];
1639  }
1640  else
1641  {
1642  $params["baseClass"] = $new_baseclass;
1643  }
1644 
1645  return $params;
1646  }
1647 
1651  private function getCidForClass($a_class, $a_check = false)
1652  {
1653  if ($this->class_cid[$a_class] == "")
1654  {
1655  $this->readClassInfo($a_class);
1656  }
1657  if ($this->class_cid[$a_class] == "")
1658  {
1659  if ($a_check)
1660  {
1661  return false;
1662  }
1663  if (DEVMODE == 1)
1664  {
1665  $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
1666  may solve the issue by putting an empty * @ilCtrl_Calls [YourClassName]: into your class header.".
1667  " In both cases you need to reload the control structure in the setup.";
1668  }
1669  include_once("./Services/UICore/exceptions/class.ilCtrlException.php");
1670  throw new ilCtrlException("Cannot find cid for class ".$a_class.".".$add);
1671  }
1672  return $this->class_cid[$a_class];
1673  }
1674 
1678  private function getClassForCid($a_cid)
1679  {
1680  if ($this->cid_class[$a_cid] == "")
1681  {
1682  $this->readCidInfo($a_cid);
1683  }
1684  if ($this->cid_class[$a_cid] == "")
1685  {
1686  include_once("./Services/UICore/exceptions/class.ilCtrlException.php");
1687  throw new ilCtrlException("Cannot find class for cid ".$a_cid.".");
1688  }
1689  return $this->cid_class[$a_cid];
1690  }
1691 
1697  private function readCidInfo($a_cid)
1698  {
1699  global $ilDB;
1700 
1701  if (isset($this->info_read_cid[$a_cid]))
1702  {
1703  return;
1704  }
1705 
1706  $cached_ctrl = ilCachedCtrl::getInstance();
1707  $rec = $cached_ctrl->lookupCid($a_cid);
1708 
1709 // $set = $ilDB->query("SELECT * FROM ctrl_classfile ".
1710 // " WHERE cid = ".$ilDB->quote($a_cid, "text")
1711 // );
1712 // if ($rec = $ilDB->fetchAssoc($set))
1713  if($rec)
1714  {
1715  $this->cid_class[$a_cid] = $rec["class"];
1716  $this->class_cid[$rec["class"]] = $a_cid;
1717 
1718  $calls = $cached_ctrl->lookupCall($rec["class"]);
1719 
1720  // $set = $ilDB->query("SELECT * FROM ctrl_calls ".
1721  // " WHERE parent = ".$ilDB->quote($rec["class"], "text")
1722  // );
1723  // while ($rec2 = $ilDB->fetchAssoc($set))
1724  foreach($calls as $rec2)
1725  {
1726  if (!isset($this->calls[$rec["class"]]) || !is_array($this->calls[$rec["class"]]) || !in_array($rec2["child"], $this->calls[$rec["class"]]))
1727  {
1728  if ($rec2["child"] != "")
1729  {
1730  $this->calls[$rec["class"]][] = $rec2["child"];
1731  }
1732  }
1733  }
1734  $this->info_read_class[$rec["class"]] = true;
1735  }
1736 
1737  $this->info_read_cid[$a_cid] = true;
1738  }
1739 
1745  private function readNodeInfo($a_node)
1746  {
1747  $n_arr = explode(":", $a_node);
1748  foreach ($n_arr as $cid)
1749  {
1750  $this->readCidInfo($cid);
1751  }
1752  }
1753 
1759  private function readClassInfo($a_class)
1760  {
1761  global $ilDB;
1762 
1763  $a_class = strtolower($a_class);
1764  if (isset($this->info_read_class[$a_class]))
1765  {
1766  return;
1767  }
1768 
1769  $cached_ctrl = ilCachedCtrl::getInstance();
1770  $rec = $cached_ctrl->lookupClassFile($a_class);
1771 
1772 
1773 // $set = $ilDB->query("SELECT * FROM ctrl_classfile ".
1774 // " WHERE class = ".$ilDB->quote($a_class, "text")
1775 // );
1776 // if ($rec = $ilDB->fetchAssoc($set))
1777  if($rec)
1778  {
1779  $this->cid_class[$rec["cid"]] = $a_class;
1780  $this->class_cid[$a_class] = $rec["cid"];
1781  }
1782 
1783 // $set = $ilDB->query("SELECT * FROM ctrl_calls ".
1784 // " WHERE parent = ".$ilDB->quote($a_class, "text")
1785 // );
1786  $recs = $cached_ctrl->lookupCall($a_class);
1787 // while ($rec = $ilDB->fetchAssoc($set))
1788  foreach($recs as $rec)
1789  {
1790  if (!isset($this->calls[$a_class]) || !is_array($this->calls[$a_class]) || !in_array($rec["child"], $this->calls[$a_class]))
1791  {
1792  if ($rec["child"] != "")
1793  {
1794  $this->calls[$a_class][] = $rec["child"];
1795  }
1796  }
1797  }
1798 
1799  $this->info_read_class[$a_class] = true;
1800  $this->info_read_cid[$this->class_cid[$a_class]] = true;
1801  }
1802 
1806  private function getParentCidOfNode($a_node)
1807  {
1808  $n_arr = explode(":", $a_node);
1809  return $n_arr[count($n_arr) - 2];
1810  }
1811 
1815  private function removeLastCid($a_node)
1816  {
1817  $lpos = strrpos($a_node, ":");
1818  return substr($a_node, 0, $lpos);
1819  }
1820 
1824  private function getCurrentCidOfNode($a_node)
1825  {
1826  $n_arr = explode(":", $a_node);
1827  return $n_arr[count($n_arr) - 1];
1828  }
1829 
1836  function insertCtrlCalls($a_parent, $a_child, $a_comp_prefix)
1837  {
1838  global $ilDB;
1839 
1840  $a_parent = strtolower($a_parent);
1841  $a_child = strtolower($a_child);
1842  $a_comp_prefix = strtolower($a_comp_prefix);
1843 
1844  $set = $ilDB->query("SELECT * FROM ctrl_calls WHERE ".
1845  " parent = ".$ilDB->quote($a_parent, "text")." AND ".
1846  " child = ".$ilDB->quote($a_child, "text")." AND ".
1847  " comp_prefix = ".$ilDB->quote($a_comp_prefix, "text")
1848  );
1849  if ($rec = $ilDB->fetchAssoc($set))
1850  {
1851  return;
1852  }
1853  $ilDB->manipulate("INSERT INTO ctrl_calls ".
1854  "(parent, child, comp_prefix) VALUES (".
1855  $ilDB->quote($a_parent, "text").",".
1856  $ilDB->quote($a_child, "text").",".
1857  $ilDB->quote($a_comp_prefix, "text").
1858  ")");
1859  }
1860 
1861 }
1862 ?>