ILIAS  release_4-4 Revision
All Data Structures Namespaces Files Functions Variables Modules Pages
ilSCORM13Player.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 
5 require_once("./Services/YUI/classes/class.ilYuiUtil.php");
6 require_once("./Modules/Scorm2004/classes/class.ilObjSCORM2004LearningModule.php");
7 
14 {
15 
16  const ENABLE_GZIP = 0;
17 
18  const NONE = 0;
19  const READONLY = 1;
20  const WRITEONLY = 2;
21  const READWRITE = 3;
22 
23  static private $schema = array // order of entries matters!
24  (
25  'package' => array(
26  'user_id' => array('pattern'=>null, 'permission' => self::NONE, 'default'=>null, 'dbfield'=>user_id),
27  'learner_name' => array('pattern'=>null, 'permission' => self::NONE, 'default'=>null, 'dbfield'=>learner_name),
28  'slm_id' => array('pattern'=>null, 'permission' => self::NONE, 'default'=>null, 'dbfield'=>slm_id),
29  'mode' => array('pattern'=>null, 'permission' => self::NONE, 'default'=>null, 'dbfield'=>c_mode),
30  'credit' => array('pattern'=>null, 'permission' => self::NONE, 'default'=>null, 'dbfield'=>credit),
31  ),
32  'node' => array(
33  'accesscount' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>accesscount),
34  'accessduration' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>accessduration),
35  'accessed' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>accessed),
36  'activityAbsoluteDuration' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>activityabsduration),
37  'activityAttemptCount' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>activityattemptcount),
38  'activityExperiencedDuration' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>activityexpduration),
39  'activityProgressStatus' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>activityprogstatus),
40  'attemptAbsoluteDuration' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>attemptabsduration),
41  'attemptCompletionAmount' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>attemptcomplamount),
42  'attemptCompletionStatus' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>attemptcomplstatus),
43  'attemptExperiencedDuration' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>attemptexpduration),
44  'attemptProgressStatus' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>attemptprogstatus),
45  'audio_captioning' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>audio_captioning),
46  'audio_level' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>audio_level),
47  'availableChildren' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>availablechildren),
48  'cmi_node_id' => array('pattern'=>null, 'permission' => self::NONE, 'default'=>null, 'dbfield'=>cmi_node_id),
49  'completion' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>completion),
50  'completion_status' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>completion_status),
51  'completion_threshold' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>completion_threshold),
52  'cp_node_id' => array('pattern'=>null, 'permission' => self::NONE, 'default'=>null, 'dbfield'=>cp_node_id),
53  'created' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>created),
54  'credit' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>credit),
55  'delivery_speed' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>delivery_speed),
56  'entry' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>c_entry),
57  'exit' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>c_exit),
58  'language' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>c_language),
59  'launch_data' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>launch_data),
60  'learner_name' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>learner_name),
61  'location' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>location),
62  'max' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>c_max),
63  'min' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>c_min),
64  'mode' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>c_mode),
65  'modified' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>modified),
66  'progress_measure' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>progress_measure),
67  'raw' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>c_raw),
68  'scaled' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>scaled),
69  'scaled_passing_score' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>scaled_passing_score),
70  'session_time' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>session_time),
71  'success_status' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>success_status),
72  'suspend_data' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>suspend_data),
73  'total_time' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>total_time),
74  'user_id' => array('pattern'=>null, 'permission' => self::NONE, 'default'=>null, 'dbfield'=>user_id),
75  ),
76  'comment' => array (
77  'cmi_comment_id' => array('pattern'=>null, 'permission' => self::NONE, 'default'=>null, 'dbfield'=>cmi_comment_id),
78  'cmi_node_id' => array('pattern'=>null, 'permission' => self::NONE, 'default'=>null, 'dbfield'=>cmi_node_id),
79  'comment' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>c_comment),
80  'timestamp' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>c_timestamp),
81  'location' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>location),
82  'sourceIsLMS' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>sourceislms),
83  ),
84  'correct_response' => array(
85  'cmi_correct_response_id' => array('pattern'=>null, 'permission' => self::NONE, 'default'=>null, 'dbfield'=>cmi_correct_resp_id),
86  'cmi_interaction_id' => array('pattern'=>null, 'permission' => self::NONE, 'default'=>null, 'dbfield'=>cmi_interaction_id),
87  'pattern' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>pattern),
88  ),
89  'interaction' => array(
90  'cmi_interaction_id' => array('pattern'=>null, 'permission' => self::NONE, 'default'=>null, 'dbfield'=>cmi_interaction_id),
91  'cmi_node_id' => array('pattern'=>null, 'permission' => self::NONE, 'default'=>null, 'dbfield'=>cmi_node_id),
92  'description' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>description),
93  'id' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>id),
94  'latency' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>latency),
95  'learner_response' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>learner_response),
96  'result' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>result),
97  'timestamp' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>c_timestamp),
98  'type' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>c_type),
99  'weighting' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>weighting),
100  ),
101  'objective' => array(
102  'cmi_interaction_id' => array('pattern'=>null, 'permission' => self::NONE, 'default'=>null, 'dbfield'=>cmi_interaction_id),
103  'cmi_node_id' => array('pattern'=>null, 'permission' => self::NONE, 'default'=>null, 'dbfield'=>cmi_node_id),
104  'cmi_objective_id' => array('pattern'=>null, 'permission' => self::NONE, 'default'=>null, 'dbfield'=>cmi_objective_id),
105  'completion_status' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>completion_status),
106  'description' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>description),
107  'id' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>id),
108  'max' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>c_max),
109  'min' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>c_min),
110  'raw' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>c_raw),
111  'scaled' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>scaled),
112  'progress_measure' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>progress_measure),
113  'success_status' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>success_status),
114  'scope' => array('pattern'=>null, 'permission' => self::READWRITE, 'default'=>null, 'dbfield'=>scope),
115  ),
116  );
117 
118  private $userId;
119  public $packageId;
120  public $jsMode;
121 
122  var $ilias;
123  var $slm;
124  var $tpl;
125 
126  function __construct()
127  {
128 
129  global $ilias, $tpl, $ilCtrl, $ilUser, $lng;
130 
131  //erase next?
132  if ($_REQUEST['learnerId']) {
133  $this->userId = $_REQUEST['learnerId'];
134  } else {
135  $this->userId = $GLOBALS['USER']['usr_id'];
136  }
137  $this->packageId = (int) $_REQUEST['packageId'];
138  $this->jsMode = strpos($_SERVER['HTTP_ACCEPT'], 'text/javascript')!==false;
139 
140  $this->page = $_REQUEST['page'];
141 
142  $this->slm =& new ilObjSCORM2004LearningModule($_GET["ref_id"], true);
143 
144 
145  $this->ilias =& $ilias;
146  $this->tpl =& $tpl;
147  $this->ctrl =& $ilCtrl;
148 
149  $this->packageId=ilObject::_lookupObjectId($_GET['ref_id']);
150  $this->ref_id = $_GET['ref_id'];
151  $this->userId=$ilUser->getID();
152 
153  if ($_GET['envEditor'] != null) {
154  $this->envEditor = $_GET['envEditor'];
155  } else {
156  $this->envEditor = 0;
157  }
158 
159  }
160 
164  function &executeCommand()
165  {
166  global $ilAccess, $ilLog, $ilUser, $lng, $ilias;
167 
168  $next_class = $this->ctrl->getNextClass($this);
169  $cmd = $this->ctrl->getCmd();
170 
171  if (!$ilAccess->checkAccess("read", "", $_GET["ref_id"]))
172  {
173  $ilias->raiseError($lng->txt("permission_denied"), $ilias->error_obj->WARNING);
174  }
175 
176 //$ilLog->write("SCORM2004 Player cmd: ".$cmd);
177 
178  switch($cmd){
179 
180  case 'getRTEjs':
181  $this->getRTEjs();
182  break;
183 
184  case 'cp':
185  $this->getCPData();
186  break;
187 
188  case 'adlact':
189  $this->getADLActData();
190  break;
191 
192  case 'suspend':
193  $this->suspendADLActData();
194  break;
195 
196  case 'getSuspend':
197  $this->getSuspendData();
198  break;
199 
200  case 'gobjective':
201 // $this->writeGObjective();
202  break;
203 
204  case 'getGobjective':
205  $this->readGObjective();
206  break;
207 
208  case 'getSharedData':
209  $this->readSharedData($_GET['node_id']);
210  break;
211 
212  case 'setSharedData':
213  $this->writeSharedData($_GET['node_id']);
214  break;
215 
216  case 'cmi':
217 
218  if ($_SERVER['REQUEST_METHOD']=='POST') {
219  include_once './Modules/Scorm2004/classes/class.ilSCORM2004StoreData.php';
220  ilSCORM2004StoreData::persistCMIData($this->userId, $this->packageId,
221  $this->slm->getDefaultLessonMode(), $this->slm->getComments(),
222  $this->slm->getInteractions(), $this->slm->getObjectives());
223  //error_log("Saved CMI Data");
224  } else {
225  $this->fetchCMIData();
226  }
227  break;
228 
229  case 'specialPage':
230  $this->specialPage();
231  break;
232 
233  case 'debugGUI':
234  $this->debugGUI();
235  break;
236  case 'postLogEntry':
237  $this->postLogEntry();
238  break;
239  case 'liveLogContent':
240  $this->liveLogContent();
241  break;
242  case 'downloadLog':
243  $this->downloadLog();
244  break;
245  case 'openLog':
246  $this->openLog();
247  break;
248 
249  case 'pingSession':
250  $this->pingSession();
251  break;
252  case 'scormPlayerUnload':
253  include_once './Modules/Scorm2004/classes/class.ilSCORM2004StoreData.php';
254  ilSCORM2004StoreData::scormPlayerUnload($this->userId, $this->packageId);
255  break;
256 
257  // case 'getConfigForPlayer':
258  // $this->getConfigForPlayer();
259  // break;
260  default:
261  $this->getPlayer();
262  break;
263  }
264 
265  }
266 
267  function getRTEjs()
268  {
269  $js_data = file_get_contents("./Modules/Scorm2004/scripts/buildrte/rte.js");
270  if (self::ENABLE_GZIP==1) {
271  ob_start("ob_gzhandler");
272  header('Content-Type: text/javascript; charset=UTF-8');
273  } else {
274  header('Content-Type: text/javascript; charset=UTF-8');
275  }
276  echo $js_data;
277  }
278 
279 
280  function getDataDirectory()
281  {
282  $webdir=str_replace("/ilias.php","",$_SERVER["SCRIPT_NAME"]);
283  //load ressources always with absolute URL..relative URLS fail on innersco navigation on certain browsers
284  $lm_dir=$webdir."/".ILIAS_WEB_DIR."/".$this->ilias->client_id ."/lm_data"."/lm_".$this->packageId;
285  return $lm_dir;
286  }
287 
288  //config data also used for SOP
289  public function getConfigForPlayer()
290  {
291  global $ilUser,$ilias,$ilSetting;
292  $initSuspendData = null;
293  $cmi_learner_id = (string) $ilUser->getID();
294  $lm_set = new ilSetting("lm");
295  if($lm_set->get("scorm_login_as_learner_id") == 1) {
296  $cmi_learner_id = (string) $ilUser->getLogin();
297  }
298  $config = array
299  (
300  'scope'=>$this->getScope(),
301  'learner_id' => (string) $ilUser->getID(),
302  'cmi_learner_id' => $cmi_learner_id,
303  'course_id' => (string) $this->packageId,
304  'learner_name' => $ilUser->getFirstname()." ".$ilUser->getLastname(),
305  'mode' => $this->slm->getDefaultLessonMode(),
306  'credit' => $this->slm->getCreditMode(),
307  'auto_review' => $this->slm->getAutoReviewChar(),
308  'hide_navig' => $this->slm->getHideNavig(),
309  'hide_menu' => $this->slm->getNoMenu(),
310  'ie_force_render' => $this->slm->getIe_force_render(),
311  'fourth_edition' => $this->slm->getFourth_edition(),
312  'sequencing_enabled' => $this->slm->getSequencing(),
313  'interactions_storable' => $this->slm->getInteractions(),
314  'objectives_storable' => $this->slm->getObjectives(),
315  'comments_storable' => $this->slm->getComments(),
316  'time_from_lms' => $this->slm->getTime_from_lms(),
317  'auto_last_visited' => $this->slm->getAuto_last_visited(),
318  'checkSetValues' => $this->slm->getCheck_values(),
319  'auto_suspend' => $this->slm->getAutoSuspend(),
320  'suspend_data' => $initSuspendData,
321  'cp_data' => null,
322  'cmi_data' => null,
323  'adlact_data' => null,
324  'globalobj_data' => null
325  );
326  include_once './Modules/ScormAicc/classes/SCORM/class.ilObjSCORMInitData.php';
327  $status=ilObjSCORMInitData::getStatus($this->packageId, $ilUser->getID());
328  $status['last_visited']=null;
329  if($this->slm->getAuto_last_visited())
330  {
331  $status['last_visited']=$this->get_last_visited($this->packageId, $ilUser->getID());
332  }
333  $config['status'] = $status;
334 
335  return $config;
336  }
337 
338  public function getPlayer()
339  {
340  global $ilUser,$lng, $ilias, $ilSetting;
341  // player basic config data
342 
343 
344  $initSuspendData = null;
345  $initAdlactData = null;
346  if ($this->slm->getSequencing() == true) {
347  $initSuspendData = json_decode($this->getSuspendDataInit());
348  $initAdlactData = json_decode($this->getADLActDataInit());
349  $initGlobalobjData = $this->readGObjectiveInit();
350  }
351 
352  $config = $this->getConfigForPlayer();
353 
354  //session
355  if ($this->slm->getSession()) {
356 // $session_timeout = (int)($ilias->ini->readVariable("session","expire"))/2;
357  $session_timeout = (int)ilSession::getIdleValue()/2;
358  } else {
359  $session_timeout = 0;
360  }
361  $config['session_ping'] = $session_timeout;
362 
363  //url strings
364  $store_url = 'ilias.php?baseClass=ilSAHSPresentationGUI' .'&cmd=cmi&ref_id='.$_GET["ref_id"];
365  $unload_url = 'ilias.php?baseClass=ilSAHSPresentationGUI' .'&cmd=scormPlayerUnload&ref_id='.$_GET["ref_id"];
366  if ($this->slm->getSessionDeactivated()){
367  $store_url = 'storeScorm2004.php?package_id='.$this->packageId.'&ref_id='.$_GET["ref_id"].'&client_id='.$this->ilias->client_id.'&do=store';
368  $unload_url = 'storeScorm2004.php?package_id='.$this->packageId.'&ref_id='.$_GET["ref_id"].'&client_id='.$this->ilias->client_id.'&do=unload';
369  }
370  $config['cp_url'] = 'ilias.php?baseClass=ilSAHSPresentationGUI' . '&cmd=cp&ref_id='.$_GET["ref_id"];
371  $config['cmi_url'] = 'ilias.php?baseClass=ilSAHSPresentationGUI' .'&cmd=cmi&ref_id='.$_GET["ref_id"];
372  $config['store_url'] = $store_url;
373  $config['get_adldata_url'] = 'ilias.php?baseClass=ilSAHSPresentationGUI' .'&cmd=getSharedData&ref_id='.$_GET["ref_id"];
374  $config['set_adldata_url'] = 'ilias.php?baseClass=ilSAHSPresentationGUI' . '&cmd=setSharedData&ref_id=' . $_GET["ref_id"];
375  $config['adlact_url'] = 'ilias.php?baseClass=ilSAHSPresentationGUI' .'&cmd=adlact&ref_id='.$_GET["ref_id"];
376  $config['specialpage_url'] = 'ilias.php?baseClass=ilSAHSPresentationGUI' .'&cmd=specialPage&ref_id='.$_GET["ref_id"];
377  $config['suspend_url'] = 'ilias.php?baseClass=ilSAHSPresentationGUI' .'&cmd=suspend&ref_id='.$_GET["ref_id"];
378  $config['get_suspend_url'] = 'ilias.php?baseClass=ilSAHSPresentationGUI' .'&cmd=getSuspend&ref_id='.$_GET["ref_id"];
379  //next 2 lines could be deleted later
380  $config['gobjective_url'] = 'ilias.php?baseClass=ilSAHSPresentationGUI' .'&cmd=gobjective&ref_id='.$_GET["ref_id"];
381  $config['get_gobjective_url'] = 'ilias.php?baseClass=ilSAHSPresentationGUI' .'&cmd=getGobjective&ref_id='.$_GET["ref_id"];
382  $config['ping_url'] = 'ilias.php?baseClass=ilSAHSPresentationGUI' .'&cmd=pingSession&ref_id='.$_GET["ref_id"];
383  $config['scorm_player_unload_url']= $unload_url;
384  $config['post_log_url'] = 'ilias.php?baseClass=ilSAHSPresentationGUI' .'&cmd=postLogEntry&ref_id='.$_GET["ref_id"];
385  $config['livelog_url'] = 'ilias.php?baseClass=ilSAHSPresentationGUI' .'&cmd=liveLogContent&ref_id='.$_GET["ref_id"];
386  $config['package_url'] = $this->getDataDirectory()."/";
387 
388  //editor
389  $config['envEditor'] = $this->envEditor;
390 
391  //debug
392  $config['debug'] = $this->slm->getDebug();
393  $config['debug_fields'] = $this->getDebugValues();
394  $config['debug_fields_test'] = $this->getDebugValues(true);
395 
396 
397  //language strings
398  $langstrings['btnStart'] = $lng->txt('scplayer_start');
399  $langstrings['btnExit'] = $lng->txt('scplayer_exit');
400  $langstrings['btnExitAll'] = $lng->txt('scplayer_exitall');
401  $langstrings['btnSuspendAll'] = $lng->txt('scplayer_suspendall');
402  $langstrings['btnPrevious'] = $lng->txt('scplayer_previous');
403  $langstrings['btnContinue'] = $lng->txt('scplayer_continue');
404  $langstrings['btnhidetree']=$lng->txt('scplayer_hidetree');
405  $langstrings['btnshowtree']=$lng->txt('scplayer_showtree');
406  $langstrings['linkexpandTree']=$lng->txt('scplayer_expandtree');
407  $langstrings['linkcollapseTree']=$lng->txt('scplayer_collapsetree');
408  $langstrings['contCreditOff']=$lng->txt('cont_credit_off');
409  $config['langstrings'] = $langstrings;
410 
411  //template variables
412  //$this->tpl = new ilTemplate("tpl.scorm2004.player.html", false, false, "Modules/Scorm2004");
413  $this->tpl = new ilTemplate("tpl.scorm2004.player.html", true, true, "Modules/Scorm2004");
414 
415  // include ilias rte css, if given
416  $rte_css = $this->slm->getDataDirectory()."/ilias_css_4_2/css/style.css";
417  if (is_file($rte_css))
418  {
419  $this->tpl->setCurrentBlock("rte_css");
420  $this->tpl->setVariable("RTE_CSS", $rte_css);
421  $this->tpl->parseCurrentBlock();
422  }
423 
424 
425  $this->tpl->setVariable('JSON_LANGSTRINGS', json_encode($langstrings));
426  include_once("./Services/YUI/classes/class.ilYuiUtil.php");
427  $this->tpl->setVariable('YUI_PATH', ilYuiUtil::getLocalPath());
428  $this->tpl->setVariable('TREE_JS', "./Services/UIComponent/NestedList/js/ilNestedList.js");
429  $this->tpl->setVariable($langstrings);
430  $this->tpl->setVariable('DOC_TITLE', 'ILIAS SCORM 2004 Player');
431  if ($this->slm->getIe_compatibility()) $this->tpl->setVariable('IE_COMPATIBILITY', '<meta http-equiv="X-UA-Compatible" content="IE=7" />');
432  $this->tpl->setVariable("LOCATION_STYLESHEET", ilUtil::getStyleSheetLocation());
433  $this->tpl->setVariable('INIT_CP_DATA', json_encode(json_decode($this->getCPDataInit())));
434  $this->tpl->setVariable('INIT_CMI_DATA', json_encode($this->getCMIData($this->userId, $this->packageId)));
435  $this->tpl->setVariable('INIT_ADLACT_DATA', json_encode($initAdlactData));
436  $this->tpl->setVariable('INIT_GLOBALOBJ_DATA', json_encode($initGlobalobjData));
437  $this->tpl->setVariable('JS_DATA', json_encode($config));
438  list($tsfrac, $tsint) = explode(' ', microtime());
439  $this->tpl->setVariable('TIMESTAMP', sprintf('%d%03d', $tsint, 1000*(float)$tsfrac));
440  $this->tpl->setVariable('BASE_DIR', './Modules/Scorm2004/');
441  $this->tpl->setVariable('TXT_COLLAPSE',$lng->txt('scplayer_collapsetree'));
442  if ($this->slm->getDebug()) {
443  $this->tpl->setVariable('TXT_DEBUGGER',$lng->txt('scplayer_debugger'));
444  $this->tpl->setVariable('DEBUG_URL',"PopupCenter('ilias.php?baseClass=ilSAHSPresentationGUI&cmd=debugGUI&ref_id=".$_GET["ref_id"]."','Debug',800,600);");
445  } else {
446  $this->tpl->setVariable('TXT_DEBUGGER','');
447  $this->tpl->setVariable('DEBUG_URL','');
448  }
449 
450  //set icons path
451  $this->tpl->setVariable('INLINE_CSS', ilSCORM13Player::getInlineCss());
452 
453  //include scripts
454  if ($this->slm->getCacheDeactivated()){
455  $this->tpl->setVariable('JS_SCRIPTS', 'ilias.php?baseClass=ilSAHSPresentationGUI' .'&cmd=getRTEjs&ref_id='.$_GET["ref_id"]);
456  } else {
457  $this->tpl->setVariable('JS_SCRIPTS', './Modules/Scorm2004/scripts/buildrte/rte-min.js');
458  }
459 
460  //disable top menu
461  if ($this->slm->getNoMenu()=="y") {
462  $this->tpl->setVariable("VAL_DISPLAY", "style=\"display:none;\"");
463  } else {
464  $this->tpl->setVariable("VAL_DISPLAY", "");
465  }
466 
467 
468  //check for max_attempts and raise error if max_attempts is exceeded
469  if ($this->get_max_attempts()!=0) {
470  if ($this->get_actual_attempts() >= $this->get_max_attempts()) {
471  header('Content-Type: text/html; charset=utf-8');
472  echo($lng->txt("cont_sc_max_attempt_exceed"));
473  exit;
474  }
475  }
476 
477  //count attempt
479  $this->resetSharedData();
480 
481  $this->tpl->show("DEFAULT", false);
482  }
483 
487  function getInlineCSS()
488  {
489  $is_tpl = new ilTemplate("tpl.scorm2004.inlinecss.html", true, true, "Modules/Scorm2004");
490  $is_tpl->setVariable('IC_ASSET', ilUtil::getImagePath("scorm/asset_s.png",false));
491  $is_tpl->setVariable('IC_COMPLETED', ilUtil::getImagePath("scorm/completed_s.png",false));
492  $is_tpl->setVariable('IC_NOTATTEMPTED', ilUtil::getImagePath("scorm/not_attempted_s.png",false));
493  $is_tpl->setVariable('IC_RUNNING', ilUtil::getImagePath("scorm/running_s.png",false));
494  $is_tpl->setVariable('IC_INCOMPLETE', ilUtil::getImagePath("scorm/incomplete_s.png",false));
495  $is_tpl->setVariable('IC_PASSED', ilUtil::getImagePath("scorm/passed_s.png",false));
496  $is_tpl->setVariable('IC_FAILED', ilUtil::getImagePath("scorm/failed_s.png",false));
497  $is_tpl->setVariable('IC_BROWSED', ilUtil::getImagePath("scorm/browsed.png",false));
498  return $is_tpl->get();
499  }
500 
501  public function getCPData()
502  {
503  $jsdata = $this->getCPDataInit();
504  if ($this->jsMode)
505  {
506  header('Content-Type: text/javascript; charset=UTF-8');
507  print($jsdata);
508  }
509  else
510  {
511  header('Content-Type: text/plain; charset=UTF-8');
512  $jsdata = json_decode($jsdata);
513  print_r($jsdata);
514  }
515  }
516  function getCPDataInit()
517  {
518  global $ilDB;
519 
520  $res = $ilDB->queryF(
521  'SELECT jsdata FROM cp_package WHERE obj_id = %s',
522  array('integer'),
523  array($this->packageId)
524  );
525  $packageData = $ilDB->fetchAssoc($res);
526 
527  $jsdata = $packageData['jsdata'];
528  if (!$jsdata) $jsdata = 'null';
529 
530  return $jsdata;
531  }
532 
533 
534  public function getADLActDataInit()
535  {
536  global $ilDB;
537 
538  $res = $ilDB->queryF(
539  'SELECT activitytree FROM cp_package WHERE obj_id = %s',
540  array('integer'),
541  array($this->packageId)
542  );
543  $data = $ilDB->fetchAssoc($res);
544 
545  $activitytree = $data['activitytree'];
546 
547  if(!$activitytree)
548  {
549  $activitytree = 'null';
550  }
551  return $activitytree;
552  }
553 
554  public function getADLActData()
555  {
556  $activitytree = $this->getADLActDataInit();
557  if($this->jsMode)
558  {
559  header('Content-Type: text/javascript; charset=UTF-8');
560  print($activitytree);
561  }
562  else
563  {
564  header('Content-Type: text/plain; charset=UTF-8');
565  $activitytree = json_decode($activitytree);
566  print_r($activitytree);
567  }
568  }
569 
570  public function pingSession()
571  {
572  //do nothing except returning header
573  header('Content-Type: text/plain; charset=UTF-8');
574  print("");
575  }
576 
577  public function getScope()
578  {
579  global $ilDB, $ilUser;
580 
581  $res = $ilDB->queryF(
582  'SELECT global_to_system FROM cp_package WHERE obj_id = %s',
583  array('integer'),
584  array($this->packageId)
585  );
586  $data = $ilDB->fetchAssoc($res);
587 
588  $gystem = $data['global_to_system'];
589  if($gystem == 1)
590  $gsystem = 'null';
591  else
592  $gsystem = $this->packageId;
593 
594  return $gsystem;
595  }
596 
597  public function getSuspendDataInit()
598  {
599  global $ilDB, $ilUser;
600 
601  $res = $ilDB->queryF(
602  'SELECT data FROM cp_suspend WHERE obj_id = %s AND user_id = %s',
603  array('integer', 'integer'),
604  array($this->packageId, $ilUser->getId())
605  );
606  $data = $ilDB->fetchAssoc($res);
607 
608  //delete delivered suspend data
609  $ilDB->manipulateF(
610  'DELETE FROM cp_suspend WHERE obj_id = %s AND user_id = %s',
611  array('integer', 'integer'),
612  array($this->packageId, $ilUser->getId())
613  );
614  return $data['data'];
615  }
616 
617  public function getSuspendData()
618  {
619  $suspend_data = $this->getSuspendDataInit();
620  if($this->jsMode)
621  {
622  header('Content-Type: text/javascript; charset=UTF-8');
623  print($suspend_data);
624  }
625  else
626  {
627  header('Content-Type: text/plain; charset=UTF-8');
628  $suspend_data = json_decode($suspend_data);
629  print_r($suspend_data);
630  }
631  }
632 
633  public function suspendADLActData()
634  {
635  global $ilDB, $ilUser;
636 
637  $res = $ilDB->queryF(
638  'SELECT * FROM cp_suspend WHERE obj_id = %s AND user_id = %s',
639  array('integer', 'integer'),
640  array($this->packageId, $ilUser->getId())
641  );
642 
643  if(!$ilDB->numRows($res))
644  {
645  $ilDB->insert('cp_suspend', array(
646  'data' => array('clob', file_get_contents('php://input')),
647  'obj_id' => array('integer', $this->packageId),
648  'user_id' => array('integer', $ilUser->getId())
649  ));
650  }
651  else
652  {
653  $ilDB->update('cp_suspend',
654  array(
655  'data' => array('clob', file_get_contents('php://input'))
656  ),
657  array(
658  'obj_id' => array('integer', $this->packageId),
659  'user_id' => array('integer', $ilUser->getId())
660  )
661  );
662  }
663  }
664 
665  public function readGObjectiveInit()
666  {
667  global $ilDB, $ilUser;
668 
669  //get json string
670  $g_data = new stdClass();
671 
672  $global_to_system = 1;
673 
674  $res = $ilDB->queryF('SELECT global_to_system FROM cp_package WHERE obj_id = %s',
675  array('integer'),
676  array($this->packageId)
677  );
678  while($data = $ilDB->fetchAssoc($res))
679  {
680  $global_to_system = $data['global_to_system'];
681  }
682 
683  $query = 'SELECT objective_id, scope_id, satisfied, measure, user_id,
684  score_min, score_max, score_raw, completion_status,
685  progress_measure '
686  . 'FROM cmi_gobjective, cp_node, cp_mapinfo '
687  . 'WHERE (cmi_gobjective.objective_id <> %s AND cmi_gobjective.status IS NULL '
688  . 'AND cp_node.slm_id = %s AND cp_node.nodename = %s '
689  . 'AND cp_node.cp_node_id = cp_mapinfo.cp_node_id '
690  . 'AND cmi_gobjective.objective_id = cp_mapinfo.targetobjectiveid) '
691  . 'GROUP BY objective_id, scope_id, satisfied, measure, user_id,
692  score_min, score_max, score_raw, completion_status,
693  progress_measure';
694  $res = $ilDB->queryF(
695  $query,
696  array('text', 'integer', 'text'),
697  array('-course_overall_status-', $this->packageId, 'mapInfo')
698  );
699  while($row = $ilDB->fetchAssoc($res))
700  {
701  if (($global_to_system == 1 && $row['scope_id'] == 0) || ($global_to_system == 0 && $row['scope_id'] == $this->packageId)) {
702  $learner = $row['user_id'];
703  $objective_id = $row['objective_id'];
704  if($row['scope_id'] == 0)
705  {
706  $scope = "null";
707  }
708  else
709  {
710  $scope = $row['scope_id'];
711  }
712 
713  if($row['satisfied'] != NULL)
714  {
715  $toset = $row['satisfied'];
716  $g_data->{"satisfied"}->{$objective_id}->{$learner}->{$scope} = $toset;
717  }
718 
719  if($row['measure'] != NULL)
720  {
721  $toset = $row['measure'];
722  $g_data->{"measure"}->{$objective_id}->{$learner}->{$scope} = $toset;
723  }
724 
725  if($row['score_raw'] != NULL)
726  {
727  $toset = $row['score_raw'];
728  $g_data->{"score_raw"}->{$objective_id}->{$learner}->{$scope} = $toset;
729  }
730 
731  if($row['score_min'] != NULL)
732  {
733  $toset = $row['score_min'];
734  $g_data->{"score_min"}->{$objective_id}->{$learner}->{$scope} = $toset;
735  }
736 
737  if($row['score_max'] != NULL)
738  {
739  $toset = $row['score_max'];
740  $g_data->{"score_max"}->{$objective_id}->{$learner}->{$scope} = $toset;
741  }
742 
743  if($row['progress_measure'] != NULL)
744  {
745  $toset = $row['progress_measure'];
746  $g_data->{"progress_measure"}->{$objective_id}->{$learner}->{$scope} = $toset;
747  }
748 
749  if($row['completion_status'] != NULL)
750  {
751  $toset = $row['completion_status'];
752  $g_data->{"completion_status"}->{$objective_id}->{$learner}->{$scope} = $toset;
753  }
754  }
755  }
756  return $g_data;
757  }
758 
759  public function readGObjective()
760  {
761 
762  $gobjective_data = json_encode($this->readGObjectiveInit());
763  if ($this->jsMode)
764  {
765  header('Content-Type: text/javascript; charset=UTF-8');
766  print($gobjective_data);
767  }
768  else
769  {
770  header('Content-Type: text/plain; charset=UTF-8');
771  $gobjective_data = json_decode($gobjective_data);
772  print_r($gobjective_data);
773  }
774  }
775 
776 
777  //Read the shared datascores for a given SCO
778  public function readSharedData($sco_node_id)
779  {
780 
781  global $ilDB, $ilUser;
782  $dataStores = array( "data" => array(),
783  "permissions" => array());
784  $readPermissions = array();
785 
786  $query = 'SELECT target_id, read_shared_data, write_shared_data '
787  . 'FROM cp_datamap '
788  . 'WHERE slm_id = %s '
789  . 'AND sco_node_id = %s '
790  . 'GROUP BY target_id, read_shared_data, write_shared_data';
791 
792 
793  $res = $ilDB->queryF(
794  $query,
795  array('integer', 'integer'),
796  array($this->packageId, $sco_node_id)
797  );
798 
799  //Pass 1: Get all the shared data target_ids
800  // for this content package
801  while($row = $ilDB->fetchAssoc($res))
802  {
803  $storeVal = ($row['read_shared_data'] == 0 && $row['write_shared_data'] == 1 )
804  ? 'notWritten'
805  : null;
806 
807  $dataStores["data"][$row['target_id']] = array( "store" => $storeVal,
808  "readSharedData" => $row['read_shared_data'],
809  "writeSharedData" => $row['write_shared_data']);
810  $dataStores["readPermissions"][$row['target_id']] = $row['read_shared_data'];
811  }
812 
813  if(count($dataStores) < 1)
814  {
815  //If there are no datastores, then return nothing
816  echo "";
817  exit();
818  }
819  else if ($dataStores["readPermissions"] != null && array_sum($dataStores["readPermissions"]) != 0)
820  {
821 
822  //If there exists at least one readSharedData permission, then
823  //fill in the existing values (if any) already in the store.
824 
825  //Create the params to add to the Pass 2 query (get existing values)
826  $params = array("types" => array("integer", "integer"),
827  "values" => array($this->userId, $this->packageId));
828 
829  $paramTemplate = '';
830 
831  //See if readSharedData is set for each datamap.
832  //If set to true, then add it to the search query
833  foreach($dataStores["data"] as $key => $val)
834  {
835  if($dataStores["readPermissions"][$key] == 1
836  && $dataStores["data"][$key]["store"] != 'notWritten')
837  {
838  $params["types"][] = "text";
839  $params["values"][] = $key;
840  $paramTemplate .= '%s, ';
841  }
842  }
843 
844  //Get rid of the trailing ', '
845  $paramTemplate = substr($paramTemplate, 0, strlen($paramTemplate) - 2);
846 
847  //Pass 2: Query for values previously saved by the user
848  $query = 'SELECT target_id, store '
849  . 'FROM adl_shared_data '
850  . 'WHERE user_id = %s '
851  . 'AND slm_id = %s '
852  . 'AND target_id IN (' . $paramTemplate . ')';
853 
854 
855  $res = $ilDB->queryF(
856  $query,
857  $params["types"],
858  $params["values"]
859  );
860 
861  while($row = $ilDB->fetchAssoc($res))
862  {
863  $dataStores["data"][$row['target_id']]["store"] = $row['store'];
864  }
865  }
866 
867  header('Content-Type: text/javascript; charset=UTF-8');
868 
869  echo json_encode($dataStores["data"]);
870  }
871 
872  public function writeSharedData($sco_node_id)
873  {
874  global $ilDB, $ilUser;
875  $g_data = json_decode(file_get_contents('php://input'));
876 
877  //Step 1: Get the writeable stores for this SCO that already have values
878  $query = 'SELECT dm.target_id, sd.store '
879  . 'FROM cp_datamap dm '
880  . 'LEFT JOIN adl_shared_data sd '
881  . 'ON(dm.slm_id = sd.slm_id AND dm.target_id = sd.target_id) '
882  . 'WHERE sco_node_id = %s '
883  . 'AND dm.slm_id = %s '
884  . 'AND write_shared_data = 1 '
885  . 'AND user_id = %s';
886 
887  $res = $ilDB->QueryF(
888  $query,
889  array('integer', 'integer', 'integer'),
890  array($sco_node_id, $this->packageId, $this->userId)
891  );
892 
893  $dataStores = array();
894  $originalVals = array();
895  while($row = $ilDB->fetchAssoc($res))
896  {
897  $id = $row['target_id'];
898  $dataStores[$id] = $g_data->{$id};
899  $originalVals[$id] = $row['store'];
900  }
901 
902 
903  //Step 2: Add the writeable stores
904  foreach($g_data as $key => $obj)
905  {
906  //If it's already created in adl_shared_data, we
907  //need to update it.
908  if(array_key_exists($key, $dataStores) )
909  {
910  if($obj == 'notWritten') continue;
911 
912  $query = 'UPDATE adl_shared_data '
913  . 'SET store = %s '
914  . 'WHERE user_id = %s '
915  . 'AND target_id = %s '
916  . 'AND slm_id = %s ';
917 
918  $ilDB->manipulateF(
919  $query,
920  array('text', 'integer', 'text', 'integer'),
921  array($dataStores[$key], $this->userId, $key, $this->packageId)
922  );
923  } else
924  {
925  //Check for writability
926  $res = $ilDB->queryF(
927  'SELECT write_shared_data '
928  . 'FROM cp_datamap '
929  . 'WHERE target_id = %s '
930  . 'AND slm_id = %s '
931  . 'AND sco_node_id = %s',
932  array('text', 'integer', 'integer'),
933  array($key, $this->packageId, $sco_node_id));
934 
935  $row = $ilDB->fetchAssoc($res);
936  if($row["write_shared_data"] != 1)
937  {
938  continue;
939  }
940 
941  //If it's writeable, then add the new value into the database
942  $res = $ilDB->manipulateF(
943  'INSERT INTO adl_shared_data VALUES (%s, %s, %s, %s)',
944  array('integer', 'integer', 'text', 'text'),
945  array($this->packageId, $this->userId, $key, $obj));
946  }
947  }
948  echo "1";
949  exit();
950 
951  }
952 
953  public function specialPage() {
954 
955  global $lng;
956 
957  $specialpages = array (
958  "_COURSECOMPLETE_" => "seq_coursecomplete",
959  "_ENDSESSION_" => "seq_endsession",
960  "_SEQBLOCKED_" => "seq_blocked",
961  "_NOTHING_" => "seq_nothing",
962  "_ERROR_" => "seq_error",
963  "_DEADLOCK_" => "seq_deadlock",
964  "_INVALIDNAVREQ_" => "seq_invalidnavreq",
965  "_SEQABANDON_" => "seq_abandon",
966  "_SEQABANDONALL_" => "seq_abandonall",
967  "_TOC_" => "seq_toc"
968  );
969 
970  $this->tpl = new ilTemplate("tpl.scorm2004.specialpages.html", false, false, "Modules/Scorm2004");
971  $this->tpl->setVariable("LOCATION_STYLESHEET", ilUtil::getStyleSheetLocation());
972  $this->tpl->setVariable('TXT_SPECIALPAGE',$lng->txt($specialpages[$this->page]));
973  if ($this->page!="_TOC_" && $this->page!="_SEQABANDON_" && $this->page!="_SEQABANDONALL_" ) {
974  $this->tpl->setVariable('CLOSE_WINDOW',$lng->txt('seq_close'));
975  } else {
976  $this->tpl->setVariable('CLOSE_WINDOW',"");
977  }
978  $this->tpl->show("DEFAULT", false);
979  }
980 
981 
982  public function fetchCMIData()
983  {
984  $data = $this->getCMIData($this->userId, $this->packageId);
985  if ($this->jsMode)
986  {
987  header('Content-Type: text/javascript; charset=UTF-8');
988  print(json_encode($data));
989  }
990  else
991  {
992  header('Content-Type: text/plain; charset=UTF-8');
993  print(var_export($data, true));
994  }
995  }
996 
997 
1002  private function normalizeFields($table, &$node)
1003  {
1004  return;
1005  foreach (self::$schema[$table] as $k => $v)
1006  {
1007  $value = $node->$k;
1008  if (isset($value) && is_string($v) && !preg_match($v, $value))
1009  {
1010  unset($node->$k);
1011  }
1012  }
1013  }
1014 
1015  public function getCMIData($userId, $packageId)
1016  {
1017  global $ilDB;
1018 
1019  $i_check=0;
1020  $result = array(
1021  'schema' => array(),
1022  'data' => array()
1023  );
1024 
1025  foreach(self::$schema as $k => &$v)
1026  {
1027  $result['schema'][$k] = array_keys($v);
1028  $q = '';
1029  switch ($k)
1030  {
1031  case "node":
1032  $q = 'SELECT cmi_node.*
1033  FROM cmi_node
1034  INNER JOIN cp_node ON cmi_node.cp_node_id = cp_node.cp_node_id
1035  WHERE cmi_node.user_id = %s
1036  AND cp_node.slm_id = %s';
1037 
1038  break;
1039 
1040  case "comment":
1041  if ($i_check>7) {
1042  $i_check-=8;
1043  if ($this->slm->getComments()) $q = 'SELECT
1044  cmi_comment.cmi_comment_id,
1045  cmi_comment.cmi_node_id,
1046  cmi_comment.c_comment,
1047  cmi_comment.c_timestamp,
1048  cmi_comment.location,
1049  cmi_comment.sourceislms
1050  FROM cmi_comment
1051  INNER JOIN cmi_node ON cmi_node.cmi_node_id = cmi_comment.cmi_node_id
1052  INNER JOIN cp_node ON cp_node.cp_node_id = cmi_node.cp_node_id
1053  WHERE cmi_node.user_id = %s
1054  AND cp_node.slm_id = %s
1055  ORDER BY cmi_comment.cmi_comment_id';
1056  }
1057 
1058  break;
1059 
1060  case "correct_response":
1061  if ($i_check>3) {
1062  $i_check-=4;
1063  if ($this->slm->getInteractions()) $q = 'SELECT cmi_correct_response.*
1064  FROM cmi_correct_response
1065  INNER JOIN cmi_interaction
1066  ON cmi_interaction.cmi_interaction_id = cmi_correct_response.cmi_interaction_id
1067  INNER JOIN cmi_node ON cmi_node.cmi_node_id = cmi_interaction.cmi_node_id
1068  INNER JOIN cp_node ON cp_node.cp_node_id = cmi_node.cp_node_id
1069  WHERE cmi_node.user_id = %s
1070  AND cp_node.slm_id = %s
1071  ORDER BY cmi_correct_response.cmi_correct_resp_id';
1072  }
1073  break;
1074 
1075  case "interaction":
1076  if ($i_check>1) {
1077  $i_check-=2;
1078  if ($this->slm->getInteractions()) $q = 'SELECT
1079  cmi_interaction.cmi_interaction_id,
1080  cmi_interaction.cmi_node_id,
1081  cmi_interaction.description,
1082  cmi_interaction.id,
1083  cmi_interaction.latency,
1084  cmi_interaction.learner_response,
1085  cmi_interaction.result,
1086  cmi_interaction.c_timestamp,
1087  cmi_interaction.c_type,
1088  cmi_interaction.weighting
1089  FROM cmi_interaction
1090  INNER JOIN cmi_node ON cmi_node.cmi_node_id = cmi_interaction.cmi_node_id
1091  INNER JOIN cp_node ON cp_node.cp_node_id = cmi_node.cp_node_id
1092  WHERE cmi_node.user_id = %s
1093  AND cp_node.slm_id = %s
1094  ORDER BY cmi_interaction.cmi_interaction_id';
1095  }
1096  break;
1097 
1098  case "objective":
1099  if ($i_check>0) {
1100  if ($this->slm->getObjectives()) $q = 'SELECT
1101  cmi_objective.cmi_interaction_id,
1102  cmi_objective.cmi_node_id,
1103  cmi_objective.cmi_objective_id,
1104  cmi_objective.completion_status,
1105  cmi_objective.description,
1106  cmi_objective.id,
1107  cmi_objective.c_max,
1108  cmi_objective.c_min,
1109  cmi_objective.c_raw,
1110  cmi_objective.scaled,
1111  cmi_objective.progress_measure,
1112  cmi_objective.success_status,
1113  cmi_objective.scope
1114  FROM cmi_objective
1115  INNER JOIN cmi_node ON cmi_node.cmi_node_id = cmi_objective.cmi_node_id
1116  INNER JOIN cp_node ON cp_node.cp_node_id = cmi_node.cp_node_id
1117  WHERE cmi_node.user_id = %s
1118  AND cp_node.slm_id = %s
1119  ORDER BY cmi_objective.cmi_objective_id';
1120  }
1121  break;
1122 
1123  case "package"://delete because data exist except of learner_name
1124  $q = 'SELECT usr_data.usr_id user_id,
1125  CONCAT(CONCAT(COALESCE(usr_data.firstname, \'\'), \' \'), COALESCE(usr_data.lastname, \'\')) learner_name,
1126  sahs_lm.id slm_id , sahs_lm.default_lesson_mode "mode", sahs_lm.credit
1127  FROM usr_data, cp_package
1128  INNER JOIN sahs_lm ON cp_package.obj_id = sahs_lm.id
1129  WHERE usr_data.usr_id = %s
1130  AND sahs_lm.id = %s';
1131 
1132  break;
1133 
1134  }
1135 
1136  $result['data'][$k] = array();
1137  if ($q != '') {
1138  $types = array('integer', 'integer');
1139  $values = array($userId, $packageId);
1140  $res = $ilDB->queryF($q, $types, $values);
1141 
1142  while($row = $ilDB->fetchAssoc($res))
1143  {
1144  $tmp_result = array();
1145  foreach($row as $key => $value)
1146  {
1147  if ($k == "comment" && $key == "c_timestamp" && strpos($value,' ')==10) $value = str_replace(' ','T',$value);
1148  $tmp_result[] = $value;
1149  if($k=="node" && $key=="additional_tables" && $i_check<$value){
1150  $i_check=$value;
1151 // $GLOBALS['ilLog']->write($i_check);
1152  }
1153  }
1154  $result['data'][$k][] = $tmp_result;
1155  }
1156  }
1157  }
1158  return $result;
1159  }
1160 
1161 
1162  function quoteJSONArray($a_array)
1163  {
1164  global $ilDB;
1165 
1166  if(!is_array($a_array) or !count($a_array))
1167  {
1168  return array("''");
1169  }
1170 
1171  foreach($a_array as $k => $item)
1172  {
1173  if ($item != null) {
1174  $a_array[$k] = $ilDB->quote($item);
1175  } else {
1176  $a_array[$k] = "NULL";
1177  }
1178  }
1179 
1180  return $a_array;
1181  }
1182 
1190  public function getMimetype($filename)
1191  {
1192  include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
1194  }
1195 
1201  public function getCookie()
1202  {
1203  return unserialize(base64_decode($_COOKIE[IL_OP_COOKIE_NAME]));
1204  }
1205 
1206  public function setCookie($cook)
1207  {
1208  setCookie(IL_OP_COOKIE_NAME, base64_encode(serialize($cook)));
1209  }
1210 
1217  public function readFile($path)
1218  {
1219  if (headers_sent())
1220  {
1221  die('Error: Cookie could not be established');
1222  }
1223 
1224  $SAHS_LM_POSITION = 1; // index position of sahs_lm id in splitted path_info
1225 
1226  $comp = explode('/', (string) $path);
1227  $sahs = $comp[$SAHS_LM_POSITION];
1228  $cook = $this->getCookie();
1229  $perm = $cook[$sahs];
1230 
1231  if (!$perm)
1232  {
1233  // check login an package access
1234  // TODO add rbac check function here
1235  $perm = 1;
1236  if (!$perm)
1237  {
1238  header('HTTP/1.0 401 Unauthorized');
1239  die('/* Unauthorized */');
1240  }
1241  // write cookie
1242  $cook[$sahs] = $perm;
1243  $this->setCookie($cook);
1244  }
1245 
1246  $path = '.' . $path;
1247  if (!is_file($path))
1248  {
1249  header('HTTP/1.0 404 Not Found');
1250  die('/* Not Found ' . $path . '*/');
1251  }
1252 
1253  // send mimetype to client
1254  header('Content-Type: ' . $this->getMimetype($path));
1255 
1256  // let page be cached in browser for session duration
1257  header('Expires: ' . gmdate('D, d M Y H:i:s', time() + session_cache_expire()*60) . ' GMT');
1258  header('Cache-Control: private');
1259 
1260  // now show it to the user and be fine
1261  readfile($path);
1262  die();
1263  }
1264 
1268  function get_max_attempts()
1269  {
1270  include_once "./Modules/ScormAicc/classes/SCORM/class.ilObjSCORMInitData.php";
1271  return ilObjSCORMInitData::get_max_attempts($this->packageId);
1272  }
1273 
1275  {
1276  global $ilDB;
1277 
1278  $res = $ilDB->queryF(
1279  'SELECT module_version FROM sahs_lm WHERE id = %s',
1280  array('integer'),
1281  array($this->packageId));
1282  $row = $ilDB->fetchAssoc($res);
1283 
1284  return $row['module_version'];
1285  }
1286 
1291  {
1292  global $ilDB, $ilUser;
1293  $val_set = $ilDB->queryF('SELECT package_attempts FROM sahs_user WHERE obj_id = %s AND user_id = %s',
1294  array('integer','integer'), array($this->packageId,$this->userId));
1295  $val_rec = $ilDB->fetchAssoc($val_set);
1296  $attempts = $val_rec["package_attempts"];
1297  if ($attempts == null) $attempts = 0;
1298  return $attempts;
1299  }
1300 
1305  {
1306  global $ilDB, $ilUser;
1307  $res = $ilDB->queryF(
1308  'SELECT package_attempts,count(*) cnt FROM sahs_user WHERE obj_id = %s AND user_id = %s GROUP BY package_attempts',
1309  array('integer','integer'),
1310  array($this->slm->getId(),$ilUser->getId()));
1311  $val_rec = $ilDB->fetchAssoc($res);
1312  if ($val_rec["cnt"] == 0) { //offline_mode could be inserted
1313  $attempts = 1;
1314  $ilDB->manipulateF(
1315  'INSERT INTO sahs_user (obj_id,user_id,package_attempts,module_version,last_access) VALUES(%s,%s,%s,%s,%s)',
1316  array('integer', 'integer', 'integer', 'integer', 'timestamp'),
1317  array($this->slm->getId(), $ilUser->getId(), $attempts, $this->slm->getModuleVersion(), date('Y-m-d H:i:s')));
1318  } else {
1319  $attempts = $val_rec["package_attempts"];
1320  if ($attempts == null) $attempts = 0;
1321  $attempts++;
1322  $ilDB->manipulateF(
1323  'UPDATE sahs_user SET package_attempts = %s, module_version = %s, last_access=%s WHERE obj_id = %s AND user_id = %s ',
1324  array('integer', 'integer', 'timestamp', 'integer', 'integer'),
1325  array($attempts, $this->slm->getModuleVersion(), date('Y-m-d H:i:s'), $this->slm->getId(), $ilUser->getId()));
1326  }
1327  }
1328 
1329  function resetSharedData()
1330  {
1331  global $ilDB;
1332  //Reset the shared data stores if sharedDataGlobalToSystem is false
1333  $res = $ilDB->queryF('
1334  SELECT shared_data_global_to_system
1335  FROM cp_package
1336  WHERE obj_id = %s',
1337  array('integer'),
1338  array($this->packageId)
1339  );
1340 
1341  $shared_global_to_sys = $ilDB->fetchObject($res)->shared_data_global_to_system;
1342 
1343  $res = $ilDB->queryF('
1344  SELECT data
1345  FROM cp_suspend
1346  WHERE obj_id = %s
1347  AND user_id = %s',
1348  array('integer', 'integer'),
1349  array($this->packageId, $this->userId)
1350  );
1351 
1352  $suspended = false;
1353 
1354  $dat = $ilDB->fetchObject($res)->data;
1355  if($dat != null && $dat != '' ) $suspended = true;
1356 
1357  if($shared_global_to_sys == 0 && !$suspended)
1358  {
1359  $ilDB->manipulateF('
1360  DELETE FROM adl_shared_data
1361  WHERE slm_id = %s
1362  AND user_id = %s',
1363  array('integer', 'integer'),
1364  array($this->packageId, $this->userId)
1365  );
1366  }
1367  }
1368 
1369  //debug extentions
1370 
1371  private function getNodeData($sco_id,$fh)
1372  {
1373  global $ilDB,$ilLog;
1374 
1375  $fieldList = "cmi_node.cp_node_id, cmi_node.completion_threshold, cmi_node.c_exit, cmi_node.completion_status, cmi_node.progress_measure, cmi_node.success_status, cmi_node.scaled, cmi_node.session_time,".
1376  "cmi_node.c_min, cmi_node.c_max, cmi_node.c_raw, cmi_node.location, cmi_node.suspend_data, cmi_node.scaled_passing_score, cmi_node.total_time";
1377 
1378 
1379  $res = $ilDB->queryF('
1380  SELECT '.$fieldList.'
1381  FROM cmi_node,cp_node,cp_item
1382  WHERE cp_node.slm_id = %s
1383  AND cp_node.cp_node_id = cp_item.cp_node_id
1384  AND cp_item.id = %s
1385  AND cmi_node.cp_node_id = cp_item.cp_node_id
1386  AND cmi_node.user_id = %s',
1387  array('integer','text','integer'),
1388  array($this->packageId, $sco_id, $this->userId)
1389  );
1390  $row = $ilDB->fetchAssoc($res);
1391  $ilLog->write("DEBUG SQL".$row);
1392  return $row;
1393  }
1394 
1395  private function logTmpName()
1396  {
1397  $filename = $this->logDirectory()."/".$this->packageId.".tmp";
1398  if (!file_exists($filename)) {
1399  umask(0000);
1400  $fHandle = fopen($filename, 'a') or die("can't open file");
1401  fwrite($fHandle, $string);
1402  fclose($fHandle);
1403  }
1404  return $filename;
1405  }
1406 
1407  private function summaryFileName()
1408  {
1409  $filename = $this->logDirectory()."/".$this->packageId."_summary_".$this->get_actual_attempts();
1410  $adder = "0";
1411  $suffix = ".csv";
1412  $i = 0;
1413  while (file_exists($filename."_".$adder.$suffix)) {
1414  $i++;
1415  $adder = (string) $i;
1416  }
1417  $retname = $filename."_".$adder.$suffix;
1418 
1419  if (!file_exists($retname)) {
1420  umask(0000);
1421  $fHandle = fopen($retname, 'a') or die("can't open file");
1422  fwrite($fHandle, $string);
1423  fclose($fHandle);
1424  }
1425  return $retname;
1426  }
1427 
1428  private function logFileName()
1429  {
1430  global $lng;
1431  $lng->loadLanguageModule("scormdebug");
1432 
1433  $filename = $this->logDirectory()."/".$this->packageId."_".$this->get_actual_attempts();
1434  $path_csv = $filename.".csv";
1435  $path_txt = $filename.".html";
1436  if (!file_exists($path_csv)) {
1437  umask(0000);
1438  $fHandle = fopen($path_csv, 'a') or die("can't open file");
1439  $string = '"CourseId";"ScoId";"ScoTitle";"Timestamp";"Action";"Key";"Value";"Return Value";"Errorcode";"Timespan";"ErrorDescription"'."\n";
1440  fwrite($fHandle, $string);
1441  fclose($fHandle);
1442  }
1443  if (!file_exists($path_txt)) {
1444  if (file_exists($this->logTmpName())) {
1445  unlink($this->logTmpName());
1446  }
1447  umask(0000);
1448  $fHandle2 = fopen($path_txt, 'a') or die("can't open file");
1449  $logtpl = $this->getLogTemplate();
1450  $logtpl->setCurrentBlock('NewLog');
1451  $logtpl->setVariable("COURSETITLE", $this->slm->getTitle());
1452  $logtpl->setVariable("COURSEID", $this->packageId);
1453  $logtpl->setVariable("TIMESTAMP", date("d.m.Y H:i",time()));
1454  $logtpl->setVariable("SESSION", $this->get_actual_attempts());
1455  $logtpl->setVariable("error0", $lng->txt("error0"));
1456  $logtpl->setVariable("error101", $lng->txt("error101"));
1457  $logtpl->setVariable("error102", $lng->txt("error102"));
1458  $logtpl->setVariable("error103", $lng->txt("error103"));
1459  $logtpl->setVariable("error104", $lng->txt("error104"));
1460  $logtpl->setVariable("error111", $lng->txt("error111"));
1461  $logtpl->setVariable("error112", $lng->txt("error112"));
1462  $logtpl->setVariable("error113", $lng->txt("error113"));
1463  $logtpl->setVariable("error122", $lng->txt("error122"));
1464  $logtpl->setVariable("error123", $lng->txt("error123"));
1465  $logtpl->setVariable("error132", $lng->txt("error132"));
1466  $logtpl->setVariable("error133", $lng->txt("error133"));
1467  $logtpl->setVariable("error142", $lng->txt("error142"));
1468  $logtpl->setVariable("error143", $lng->txt("error143"));
1469  $logtpl->setVariable("error201", $lng->txt("error201"));
1470  $logtpl->setVariable("error301", $lng->txt("error301"));
1471  $logtpl->setVariable("error351", $lng->txt("error351"));
1472  $logtpl->setVariable("error391", $lng->txt("error391"));
1473  $logtpl->setVariable("error401", $lng->txt("error401"));
1474  $logtpl->setVariable("error402", $lng->txt("error402"));
1475  $logtpl->setVariable("error403", $lng->txt("error403"));
1476  $logtpl->setVariable("error404", $lng->txt("error404"));
1477  $logtpl->setVariable("error405", $lng->txt("error405"));
1478  $logtpl->setVariable("error406", $lng->txt("error406"));
1479  $logtpl->setVariable("error407", $lng->txt("error407"));
1480  $logtpl->setVariable("error408", $lng->txt("error408"));
1481  $logtpl->setVariable("SetValue", $lng->txt("SetValue"));
1482  $logtpl->setVariable("GetValue", $lng->txt("GetValue"));
1483  $logtpl->setVariable("Commit", $lng->txt("Commit"));
1484  $logtpl->setVariable("Initialize", $lng->txt("Initialize"));
1485  $logtpl->setVariable("Terminate", $lng->txt("Terminate"));
1486  $logtpl->setVariable("GetErrorString", $lng->txt("GetErrorString"));
1487  $logtpl->setVariable("GetLastError", $lng->txt("GetLastError"));
1488  $logtpl->setVariable("GetDiagnostic", $lng->txt("GetDiagnostic"));
1489  $logtpl->setVariable("cmi._version", $lng->txt("cmi._version"));
1490  $logtpl->setVariable("cmi.comments_from_learner._children", $lng->txt("cmi.comments_from_learner._children"));
1491  $logtpl->setVariable("cmi.comments_from_learner._count", $lng->txt("cmi.comments_from_learner._count"));
1492  $logtpl->setVariable("cmi.comments_from_learner.n.comment", $lng->txt("cmi.comments_from_learner.n.comment"));
1493  $logtpl->setVariable("cmi.comments_from_learner.n.location", $lng->txt("cmi.comments_from_learner.n.location"));
1494  $logtpl->setVariable("cmi.comments_from_learner.n.timestamp", $lng->txt("cmi.comments_from_learner.n.timestamp"));
1495  $logtpl->setVariable("cmi.comments_from_lms._children", $lng->txt("cmi.comments_from_lms._children"));
1496  $logtpl->setVariable("cmi.comments_from_lms._count", $lng->txt("cmi.comments_from_lms._count"));
1497  $logtpl->setVariable("cmi.comments_from_lms.n.comment", $lng->txt("cmi.comments_from_lms.n.comment"));
1498  $logtpl->setVariable("cmi.comments_from_lms.n.location", $lng->txt("cmi.comments_from_lms.n.location"));
1499  $logtpl->setVariable("cmi.comments_from_lms.n.timestamp", $lng->txt("cmi.comments_from_lms.n.timestamp"));
1500  $logtpl->setVariable("cmi.completion_status", $lng->txt("cmi.completion_status"));
1501  $logtpl->setVariable("cmi.completion_threshold", $lng->txt("cmi.completion_threshold"));
1502  $logtpl->setVariable("cmi.credit", $lng->txt("cmi.credit"));
1503  $logtpl->setVariable("cmi.entry", $lng->txt("cmi.entry"));
1504  $logtpl->setVariable("cmi.exit", $lng->txt("cmi.exit"));
1505  $logtpl->setVariable("cmi.interactions._children", $lng->txt("cmi.interactions._children"));
1506  $logtpl->setVariable("cmi.interactions._count", $lng->txt("cmi.interactions._count"));
1507  $logtpl->setVariable("cmi.interactions.n.id", $lng->txt("cmi.interactions.n.id"));
1508  $logtpl->setVariable("cmi.interactions.n.type", $lng->txt("cmi.interactions.n.type"));
1509  $logtpl->setVariable("cmi.interactions.n.objectives._count", $lng->txt("cmi.interactions.n.objectives._count"));
1510  $logtpl->setVariable("cmi.interactions.n.objectives.n.id", $lng->txt("cmi.interactions.n.objectives.n.id"));
1511  $logtpl->setVariable("cmi.interactions.n.timestamp", $lng->txt("cmi.interactions.n.timestamp"));
1512  $logtpl->setVariable("cmi.interactions.n.correct_responses._count", $lng->txt("cmi.interactions.n.correct_responses._count"));
1513  $logtpl->setVariable("cmi.interactions.n.correct_responses.n.pattern", $lng->txt("cmi.interactions.n.correct_responses.n.pattern"));
1514  $logtpl->setVariable("cmi.interactions.n.weighting", $lng->txt("cmi.interactions.n.weighting"));
1515  $logtpl->setVariable("cmi.interactions.n.learner_response", $lng->txt("cmi.interactions.n.learner_response"));
1516  $logtpl->setVariable("cmi.interactions.n.result", $lng->txt("cmi.interactions.n.result"));
1517  $logtpl->setVariable("cmi.interactions.n.latency", $lng->txt("cmi.interactions.n.latency"));
1518  $logtpl->setVariable("cmi.interactions.n.description", $lng->txt("cmi.interactions.n.description"));
1519  $logtpl->setVariable("cmi.launch_data", $lng->txt("cmi.launch_data"));
1520  $logtpl->setVariable("cmi.learner_id", $lng->txt("cmi.learner_id"));
1521  $logtpl->setVariable("cmi.learner_name", $lng->txt("cmi.learner_name"));
1522  $logtpl->setVariable("cmi.learner_preference._children", $lng->txt("cmi.learner_preference._children"));
1523  $logtpl->setVariable("cmi.learner_preference.audio_level", $lng->txt("cmi.learner_preference.audio_level"));
1524  $logtpl->setVariable("cmi.learner_preference.language", $lng->txt("cmi.learner_preference.language"));
1525  $logtpl->setVariable("cmi.learner_preference.delivery_speed", $lng->txt("cmi.learner_preference.delivery_speed"));
1526  $logtpl->setVariable("cmi.learner_preference.audio_captioning", $lng->txt("cmi.learner_preference.audio_captioning"));
1527  $logtpl->setVariable("cmi.location", $lng->txt("cmi.location"));
1528  $logtpl->setVariable("cmi.max_time_allowed", $lng->txt("cmi.max_time_allowed"));
1529  $logtpl->setVariable("cmi.mode", $lng->txt("cmi.mode"));
1530  $logtpl->setVariable("cmi.objectives._children", $lng->txt("cmi.objectives._children"));
1531  $logtpl->setVariable("cmi.objectives._count", $lng->txt("cmi.objectives._count"));
1532  $logtpl->setVariable("cmi.objectives.n.id", $lng->txt("cmi.objectives.n.id"));
1533  $logtpl->setVariable("cmi.objectives.n.score._children", $lng->txt("cmi.objectives.n.score._children"));
1534  $logtpl->setVariable("cmi.objectives.n.score.scaled", $lng->txt("cmi.objectives.n.score.scaled"));
1535  $logtpl->setVariable("cmi.objectives.n.score.raw", $lng->txt("cmi.objectives.n.score.raw"));
1536  $logtpl->setVariable("cmi.objectives.n.score.min", $lng->txt("cmi.objectives.n.score.min"));
1537  $logtpl->setVariable("cmi.objectives.n.score.max", $lng->txt("cmi.objectives.n.score.max"));
1538  $logtpl->setVariable("cmi.objectives.n.success_status", $lng->txt("cmi.objectives.n.success_status"));
1539  $logtpl->setVariable("cmi.objectives.n.completion_status", $lng->txt("cmi.objectives.n.completion_status"));
1540  $logtpl->setVariable("cmi.objectives.n.progress_measure", $lng->txt("cmi.objectives.n.progress_measure"));
1541  $logtpl->setVariable("cmi.objectives.n.description", $lng->txt("cmi.objectives.n.description"));
1542  $logtpl->setVariable("cmi.progress_measure", $lng->txt("cmi.progress_measure"));
1543  $logtpl->setVariable("cmi.scaled_passing_score", $lng->txt("cmi.scaled_passing_score"));
1544  $logtpl->setVariable("cmi.score._children", $lng->txt("cmi.score._children"));
1545  $logtpl->setVariable("cmi.score.scaled", $lng->txt("cmi.score.scaled"));
1546  $logtpl->setVariable("cmi.score.raw", $lng->txt("cmi.score.raw"));
1547  $logtpl->setVariable("cmi.score.min", $lng->txt("cmi.score.min"));
1548  $logtpl->setVariable("cmi.score.max", $lng->txt("cmi.score.max"));
1549  $logtpl->setVariable("cmi.session_time", $lng->txt("cmi.session_time"));
1550  $logtpl->setVariable("cmi.success_status", $lng->txt("cmi.success_status"));
1551  $logtpl->setVariable("cmi.suspend_data", $lng->txt("cmi.suspend_data"));
1552  $logtpl->setVariable("cmi.time_limit_action", $lng->txt("cmi.time_limit_action"));
1553  $logtpl->setVariable("cmi.total_time", $lng->txt("cmi.total_time"));
1554  $logtpl->setVariable("adl.nav.request", $lng->txt("adl.nav.request"));
1555  $logtpl->setVariable("adl.nav.request_valid.continue", $lng->txt("adl.nav.request_valid.continue"));
1556  $logtpl->setVariable("adl.nav.request_valid.previous", $lng->txt("adl.nav.request_valid.previous"));
1557  $logtpl->setVariable("adl.nav.request_valid.choice", $lng->txt("adl.nav.request_valid.choice"));
1558  $logtpl->setVariable("i_green", $lng->txt("i_green"));
1559  $logtpl->setVariable("i_red", $lng->txt("i_red"));
1560  $logtpl->setVariable("i_orange", $lng->txt("i_orange"));
1561  $logtpl->setVariable("i_fuchsia", $lng->txt("i_fuchsia"));
1562  $logtpl->setVariable("i_gray", $lng->txt("i_gray"));
1563  $logtpl->setVariable("error", $lng->txt("error"));
1564  $logtpl->setVariable("strange_error", $lng->txt("strange_error"));
1565  $logtpl->setVariable("strange_API-Call", $lng->txt("strange_API-Call"));
1566  $logtpl->setVariable("unknown", $lng->txt("unknown"));
1567  $logtpl->setVariable("undefined_color", $lng->txt("undefined_color"));
1568  $logtpl->setVariable("description_for", $lng->txt("description_for"));
1569  $logtpl->setVariable("hide", $lng->txt("hide"));
1570  $logtpl->setVariable("all_API-calls_shown", $lng->txt("all_API-calls_shown"));
1571  $logtpl->setVariable("show_only_important_API-calls", $lng->txt("show_only_important_API-calls"));
1572  $logtpl->setVariable("only_important_API-Calls_shown", $lng->txt("only_important_API-Calls_shown"));
1573  $logtpl->setVariable("show_all_API-calls", $lng->txt("show_all_API-calls"));
1574  $logtpl->setVariable("log_for", $lng->txt("log_for"));
1575  $logtpl->setVariable("started", $lng->txt("started"));
1576  $logtpl->setVariable("nr_session", $lng->txt("nr_session"));
1577  $logtpl->setVariable("id_learning_module", $lng->txt("id_learning_module"));
1578  if($this->slm->getCheck_values()==false) $logtpl->setVariable("CHECK_VALUES", $lng->txt("sent_values_not_checked"));
1579  $logtpl->parseCurrentBlock();
1580  fwrite($fHandle2,$logtpl->get());
1581  fclose($fHandle2);
1582  }
1583  return $filename;
1584  }
1585 
1587  {
1588  $webdir=str_replace("/ilias.php","",$_SERVER["SCRIPT_NAME"]);
1589  //load ressources always with absolute URL..relative URLS fail on innersco navigation on certain browsers
1590  $lm_dir=$webdir."/".ILIAS_WEB_DIR."/".$this->ilias->client_id ."/lm_data"."/lm_".$this->packageId;
1591  return $lm_dir;
1592  }
1593 
1594  private function logDirectory()
1595  {
1596 // $logDir=ilUtil::getDataDir()."/SCORMlogs"."/lm_".$this->packageId;
1597 // if (!file_exists($logDir)) ilUtil::makeDirParents($logDir);
1598  $logDir=$this->slm->getDataDirectory()."/logs";
1599  if (!file_exists($logDir)) {
1600  ilUtil::makeDir($logDir);
1601  }
1602  return $logDir;
1603  }
1604 
1605  public function openLog(){
1606  $filename = $_GET['logFile'];
1607  //Header
1608  header('Content-Type: text/html; charset=UTF-8');
1609  echo file_get_contents($this->logDirectory()."/".$filename);
1610  exit;
1611  }
1612 
1613  public function downloadLog(){
1614  $filename = $_GET['logFile'];
1615  //Header
1616  header("Expires: 0");
1617  header("Cache-Control: private");
1618  header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
1619  header("Pragma: cache");
1620  header("Content-Description: File Transfer");
1621  header("Content-Type: application/octet-stream");
1622  header("Content-disposition: attachment; filename=$filename");
1623  echo file_get_contents($this->logDirectory()."/".$filename);
1624  exit;
1625  }
1626 
1627  private function getLogFileList($s_delete,$s_download,$s_open)
1628  {
1629  $data = array();
1630  foreach (new DirectoryIterator($this->logDirectory()) as $fileInfo) {
1631  if ($fileInfo->isDot()) {
1632  continue;
1633  }
1634  $item['filename'] = $fileInfo->getFilename();
1635  $parts = pathinfo($item['filename']);
1636  $fnameparts = preg_split('/_/', $parts['filename'], -1, PREG_SPLIT_NO_EMPTY);
1637  $deleteUrl = '&nbsp;<a href=#'." onclick=\"javascript:deleteFile('".$item['filename']."');\">".$s_delete."</a>";
1638  //no delete for most recent file
1639  if ($this->get_actual_attempts()==$fnameparts[1]) {$deleteUrl="";}
1640 
1641  $urlDownload = 'ilias.php?baseClass=ilSAHSPresentationGUI' .'&cmd=downloadLog&ref_id='.$_GET["ref_id"].'&logFile='.$fileInfo->getFilename();
1642  $urlOpen = 'ilias.php?baseClass=ilSAHSPresentationGUI' .'&cmd=openLog&ref_id='.$_GET["ref_id"].'&logFile='.$fileInfo->getFilename();
1643  $item['date'] = date('Y/m/d H:i:s', $fileInfo->getCTime());
1644  if ($parts['extension'] == "html") {
1645  $item['action'] =$deleteUrl."&nbsp;<a href=".$urlDownload.">".$s_download."</a>&nbsp;<a target=_new href=".$urlOpen.">".$s_open."</a>";
1646  } else {
1647  $item['action'] =$deleteUrl."&nbsp;<a href=".$urlDownload.">".$s_download."</a>";
1648  }
1649  if ($parts['extension'] == "html" || $parts['extension'] == "csv") {
1650  array_push($data,$item);
1651  }
1652  }
1653  usort($data,"datecmp");
1654  return $data;
1655  }
1656 
1657  public function liveLogContent()
1658  {
1659  header('Content-Type: text/html; charset=UTF-8');
1660  print file_get_contents($this->logFileName().".html");
1661  }
1662 
1663  public function debugGUI()
1664  {
1665  global $lng;
1666  $lng->loadLanguageModule("scormdebug");
1667 
1668 /* if ($_POST['password'] == $this->slm->getDebugPw()) {
1669  $_SESSION["debug_pw"] = $this->slm->getDebugPw();
1670  }
1671  if ($_SESSION["debug_pw"]!=$this->slm->getDebugPw()) {
1672  $this->tpl = new ilTemplate("tpl.scorm2004.debug_pw.html", false, false, "./Modules/Scorm2004");
1673  $this->tpl->setVariable('SUBMIT', $lng->txt("debugwindow_submit"));
1674  $this->tpl->setVariable('CANCEL', $lng->txt("debugwindow_cancel"));
1675  $this->tpl->setVariable('PASSWORD_ENTER', $lng->txt("debugwindow_password_enter"));
1676  $this->tpl->setVariable('DEBUG_URL','ilias.php?baseClass=ilSAHSPresentationGUI' .'&cmd=debugGUI&ref_id='.$_GET["ref_id"]);
1677  } else {*/
1678  $this->tpl = new ilTemplate("tpl.scorm2004.debug.html", false, false, "./Modules/Scorm2004");
1679  $this->tpl->setVariable('CONSOLE', $lng->txt("debugwindow_console"));
1680  $this->tpl->setVariable('LOGS', $lng->txt("debugwindow_logs"));
1681  $this->tpl->setVariable('COMMENT', $lng->txt("debugwindow_comment"));
1682  $this->tpl->setVariable('COMMENT_ENTER', $lng->txt("debugwindow_comment_enter"));
1683  $this->tpl->setVariable('START_RECORDING', $lng->txt("debugwindow_start_recording"));
1684  $this->tpl->setVariable('STOP_RECORDING', $lng->txt("debugwindow_stop_recording"));
1685  $this->tpl->setVariable('DELETE_LOGFILE', $lng->txt("debugwindow_delete_logfile"));
1686  $this->tpl->setVariable('SUBMISSION_FAILED', $lng->txt("debugwindow_submission_failed"));
1687  $this->tpl->setVariable('SUBMIT', $lng->txt("debugwindow_submit"));
1688  $this->tpl->setVariable('CANCEL', $lng->txt("debugwindow_cancel"));
1689  $this->tpl->setVariable('FILENAME', $lng->txt("debugwindow_filename"));
1690  $this->tpl->setVariable('DATE', $lng->txt("debugwindow_date"));
1691  $this->tpl->setVariable('ACTION', $lng->txt("debugwindow_action"));
1692  $this->tpl->setVariable('RECORD_IMG', ilUtil::getImagePath("record.png","./Modules/Scorm2004"));
1693  $this->tpl->setVariable('STOP_IMG', ilUtil::getImagePath("stop.png","./Modules/Scorm2004"));
1694  $this->tpl->setVariable('COMMENT_IMG', ilUtil::getImagePath("comment.png","./Modules/Scorm2004"));
1695  $logfile = $this->logFileName().".html";
1696  $this->tpl->setVariable('LOGFILE',$this->logFileName().".html");
1697  $this->tpl->setVariable('FILES_DATA', json_encode($this->getLogFileList($lng->txt("debugwindow_delete"), $lng->txt("debugwindow_download"), $lng->txt("debugwindow_open"))));
1698 
1699  // path to latest yui distribution
1700  include_once "Services/YUI/classes/class.ilYuiUtil.php";
1701  $this->tpl->setVariable('PATH_YUI', ilYuiUtil::getLocalPath());
1702  //}
1703  echo $this->tpl->get("DEFAULT", true);
1704  }
1705 
1706  private function getLogTemplate()
1707  {
1708  return new ilTemplate("tpl.scorm2004.debugtxt.txt", true, true, "Modules/Scorm2004");
1709  }
1710 
1711  private function getDebugValues($test_sco = false)
1712  {
1713  global $ilDB,$ilLog;
1714  $ini_array = null;
1715  $dvalues = array();
1716 /*
1717  $res = $ilDB->queryF('
1718  SELECT debug_fields
1719  FROM sahs_lm
1720  WHERE id = %s',
1721  array('integer'),
1722  array($this->packageId)
1723  );
1724  $row = $ilDB->fetchAssoc($res);
1725  $debug_fields = $row['debug_fields'];
1726  if ($debug_fields == null) {*/
1727  $debug_fields = parse_ini_file("./Modules/Scorm2004/scripts/rtemain/debug_default.ini",true);
1728 // }
1729  if ($test_sco) {
1730  $ini_array = $debug_fields['test_sco'];
1731  } else {
1732  $ini_array = $debug_fields['normal_sco'];
1733  }
1734  foreach ($ini_array as $key => $value) {
1735  if ($value == 1) {
1736  array_push($dvalues,$key);
1737  }
1738  }
1739  return $dvalues;
1740  }
1741 
1742  public function postLogEntry()
1743  {
1744  global $ilLog,$lng;
1745  $lng->loadLanguageModule("scormdebug");
1746 
1747  $logdata = json_decode(file_get_contents('php://input'));
1748  $filename = $this->logFileName();
1749  $tmp_name = $this->logTmpName();
1750 
1751  $fh_txt = fopen($filename.".html", 'a') or die("can't open txt file");
1752  $fh_csv = fopen($filename.".csv", 'a') or die("can't open csv file");
1753  $fh_tmp = fopen($tmp_name, 'r') or die("can't open tmp file");
1754 
1755  //init tmp file
1756  if (filesize($tmp_name)>0) {
1757  $tmp_content = unserialize(fread($fh_tmp,filesize($tmp_name)));
1758  } else {
1759  $tmp_content = null;
1760  }
1761 
1762  fclose($fh_tmp);
1763 
1764  //reopen for writing
1765  $fh_tmp2 = fopen($tmp_name, 'w') or die("can't open tmp file");
1766 
1767 
1768  //write tmp
1769  $tmp_content[$logdata->scoid][$logdata->key]['value'] = $logdata->value;
1770  $tmp_content[$logdata->scoid][$logdata->key]['status'] = $logdata->result;
1771  $tmp_content[$logdata->scoid][$logdata->key]['action'] = $logdata->action;
1772 
1773  fwrite($fh_tmp2,serialize($tmp_content));
1774  fclose($fh_tmp2);
1775 
1776  $timestamp = date("d.m.Y H:i",time());
1777 
1778 
1779  $errorcode = $logdata->errorcode;
1780  $fixedFailure = false;
1781  $toleratedFailure = false;
1782  $extraErrorDescription = "";
1783  if ($errorcode == 200000) {
1784  $errorcode = 0;
1785  $toleratedFailure = true;
1786  $extraErrorDescription = "tolerated failure";
1787  }
1788  if ($errorcode>99999) {
1789  $errorcode-=100000;
1790  $fixedFailure = true;
1791  $extraErrorDescription = " failure corrected by ILIAS";
1792  }
1793  if (strpos($logdata->action,"ANALYZE")===false)
1794  {
1795  $errorDescriptions = array("0" => "",
1796  "101" => "General Exeption",
1797  "102" => "General Initialization Failure",
1798  "103" => "Already Initialized",
1799  "104" => "Content Instance Terminated",
1800  "111" => "General Termination Failure",
1801  "112" => "Termination Before Initialization",
1802  "113" => "Termination After Termination",
1803  "122" => "Retrieve Data Before Initialization",
1804  "123" => "Retrieve Data After Termination",
1805  "132" => "Store Data Before Initialization",
1806  "133" => "Store Data After Termination",
1807  "142" => "Commit Before Initialization",
1808  "143" => "Commit After Termination",
1809  "201" => "General Argument Error",
1810  "301" => "General Get Failure",
1811  "351" => "General Set Failure",
1812  "391" => "General Commit Failure",
1813  "401" => "Undefined Data Model Element",
1814  "402" => "Unimplemented Data Model Element",
1815  "403" => "Data Model Element Value Not Initialized",
1816  "404" => "Data Model Element Is Read Only",
1817  "405" => "Data Model Element Is Write Only",
1818  "406" => "Data Model Element Type Mismatch",
1819  "407" => "Data Model Element Value Out Of Range",
1820  "408" => "Data Model Dependency Not Established");
1821  $csv_string = $this->packageId.';"'
1822  .$logdata->scoid.'";"'
1823  .$logdata->scotitle.'";'
1824  .date("d.m.Y H:i",time()).';"'
1825  .$logdata->action.'";"'
1826  .$logdata->key.'";"'
1827  .str_replace("\"","\"\"",$logdata->value).'";"'
1828  .str_replace("\"","\"\"",$logdata->result).'";'
1829  .$errorcode.';'
1830  .$logdata->timespan.';"'
1831  .$errorDescriptions[$errorcode].$extraErrorDescription.'"'."\n";
1832  fwrite($fh_csv,$csv_string);
1833  }
1834 
1835  $sqlwrite = false;
1836  if($logdata->action == "Commit" || $logdata->action == "Terminate")
1837  {
1838  $sqlwrite = true;
1839  $sql_data = $this->getNodeData($logdata->scoid,$fh_csv);
1840  foreach ($sql_data as $key => $value) {
1841  $sql_string = $this->packageId.';"'
1842  .$logdata->scoid.'";"'
1843  .$logdata->scotitle.'";'
1844  .$timestamp.';"SQL";"'
1845  .$key.'";"'
1846  .str_replace("\"","\"\"",$value).'";;;;'."\n";
1847  fwrite($fh_csv,$sql_string);
1848  }
1849  }
1850 
1851  //delete files
1852  if ($logdata->action == "DELETE")
1853  {
1854  $filename = $logdata->value;
1855  $path = $this->logDirectory()."/".$filename;
1856  unlink($path);
1857  return;
1858  }
1859 
1860  //write TXT
1861  $logtpl = $this->getLogTemplate();
1862  $color = "red";
1863  $importantkey=1;
1864  $ArGetValues = array('comments_from_lms','completion_threshold','credit','entry','launch_data','learner_id','learner_name','max_time_allowed','mode','scaled_passing_score','time_limit_action','total_time');
1865 
1866  switch ($logdata->action) {
1867  case 'SetValue':
1868  if ($logdata->result == "true" && $errorcode == 0) $color = "green";
1869  if ($color=="green" && $logdata->key == "cmi.exit" && $logdata->value!="suspend") $color = "orange";
1870  if ($fixedFailure == false && $errorcode!=406) $logdata->value = '"'.$logdata->value.'"';
1871  if ($toleratedFailure == true) $color = "fuchsia";
1872  if ($fixedFailure == true) $color = "gray";
1873  break;
1874  case 'GetValue':
1875  if ($errorcode == 0) $color = "green";
1876  break;
1877  case 'Initialize':
1878  if ($errorcode == 0)
1879  {
1880  $color = "green";
1881  $logtpl->setCurrentBlock("InitializeStart");
1882  $logtpl->setVariable("SCO-title", $lng->txt("SCO-title"));
1883  $logtpl->setVariable("SCO_TITLE", $logdata->scotitle);
1884  $logtpl->setVariable("SCO-name", $lng->txt("SCO-name"));
1885  $logtpl->setVariable("SCO_NAME", $logdata->scoid);
1886  $logtpl->setVariable("started", $lng->txt("started"));
1887  $logtpl->setVariable("TIMESTAMP", $timestamp);
1888  $logtpl->setVariable("milliseconds", $lng->txt("milliseconds"));
1889  $logtpl->setVariable("API-call", $lng->txt("API-call"));
1890  $logtpl->setVariable("return_value", $lng->txt("return_value"));
1891  $logtpl->setVariable("error", $lng->txt("error"));
1892  $logtpl->parseCurrentBlock();
1893  }
1894  break;
1895  case 'Commit':
1896  if ($errorcode == 0) $color = "green";
1897  if ($fixedFailure == true) $color = "gray";
1898  break;
1899  case 'Terminate':
1900  if ($errorcode == 0) $color = "green";
1901  break;
1902  case 'GetErrorString':
1903  $importantkey=0;
1904  if ($errorcode == 0) $color = "green";
1905  break;
1906  case 'GetLastError':
1907  $logtpl->setCurrentBlock("GetLastError");
1908  $logtpl->setVariable("TIMESPAN", $logdata->timespan);
1909  $logtpl->setVariable("RESULT", $logdata->result);
1910  $logtpl->parseCurrentBlock();
1911  break;
1912  case 'GetDiagnostic':
1913  $logtpl->setCurrentBlock("GetDiagnostic");
1914  $logtpl->setVariable("TIMESPAN", $logdata->timespan);
1915  $logtpl->setVariable("KEY", $logdata->key);
1916  $logtpl->setVariable("RESULT", $logdata->result);
1917  $logtpl->parseCurrentBlock();
1918  break;
1919  case 'INFO':
1920  $logtpl->setCurrentBlock("INFO");
1921  $logtpl->setVariable("hint", $lng->txt("hint"));
1922  $logtpl->setVariable("KEY", $lng->txt($logdata->key));
1923  $logtpl->setVariable("VALUE", $logdata->value);
1924  $logtpl->parseCurrentBlock();
1925  break;
1926  case 'COMMENT':
1927  $logtpl->setCurrentBlock("COMMENT");
1928  $logtpl->setVariable("comment", $lng->txt("comment"));
1929  $logtpl->setVariable("generated", $lng->txt("generated"));
1930  $logtpl->setVariable("TIMESTAMP", $timestamp);
1931  $logtpl->setVariable("VALUE", $logdata->value);
1932  $logtpl->parseCurrentBlock();
1933  break;
1934  case 'ANALYZE':
1935  $logtpl->setCurrentBlock("ANALYZE");
1936  if (count($logdata->value) == 0) {
1937  $color = "green";
1938  $logtpl->setVariable("ANALYZE_SUMMARY", $lng->txt("no_missing_API-calls"));
1939  $logtpl->setVariable("VALUE", "");
1940  } else {
1941  $tmpvalue = "SetValue(\"".implode("\", ... ),<br/>SetValue(\"",$logdata->value)."\", ... )";
1942  for ($i=0; $i <count($ArGetValues); $i++){
1943  $tmpvalue = str_replace("SetValue(\"cmi.".$ArGetValues[$i]."\", ... )","GetValue(\"cmi.".$ArGetValues[$i]."\")",$tmpvalue);
1944  }
1945  $logtpl->setVariable("ANALYZE_SUMMARY", $lng->txt("missing_API-calls"));
1946  $logtpl->setVariable("VALUE", $tmpvalue);
1947  }
1948  $logtpl->setVariable("summary_for_SCO_without_test", $lng->txt("summary_for_SCO_without_test"));
1949  $logtpl->setVariable("generated", $lng->txt("generated"));
1950  $logtpl->setVariable("TIMESTAMP", $timestamp);
1951  $logtpl->setVariable("COLOR", $color);
1952  $logtpl->parseCurrentBlock();
1953  break;
1954  case 'ANALYZETEST':
1955  $logtpl->setCurrentBlock("ANALYZETEST");
1956  if (count($logdata->value) == 0) {
1957  $color = "green";
1958  $logtpl->setVariable("ANALYZE_SUMMARY", $lng->txt("no_missing_API-calls"));
1959  $logtpl->setVariable("VALUE", "");
1960  } else {
1961  $tmpvalue = "SetValue(\"".implode("\", ... ),<br/>SetValue(\"",$logdata->value)."\", ... )";
1962  for ($i=0; $i <count($ArGetValues); $i++){
1963  $tmpvalue = str_replace("SetValue(\"cmi.".$ArGetValues[$i]."\", ... )","GetValue(\"cmi.".$ArGetValues[$i]."\")",$tmpvalue);
1964  }
1965  $logtpl->setVariable("ANALYZE_SUMMARY", $lng->txt("missing_API-calls"));
1966  $logtpl->setVariable("VALUE", $tmpvalue);
1967  }
1968  $logtpl->setVariable("summary_for_SCO_with_test", $lng->txt("summary_for_SCO_with_test"));
1969  $logtpl->setVariable("generated", $lng->txt("generated"));
1970  $logtpl->setVariable("TIMESTAMP", $timestamp);
1971  $logtpl->setVariable("COLOR", $color);
1972  $logtpl->parseCurrentBlock();
1973  break;
1974  case 'SUMMARY':
1975  $logtpl->setCurrentBlock("SUMMARY");
1976  $logtpl->setVariable("summary_csv", $lng->txt("summary_csv"));
1977  $logtpl->setVariable("TIMESTAMP", $timestamp);
1978  $logtpl->setVariable("summary_download", $lng->txt("summary_download"));
1979  $logtpl->parseCurrentBlock();
1980  break;
1981  default:
1982  $importantkey=0;
1983  $color = "orange";
1984  break;
1985  }
1986  if ($logdata->action == 'SetValue' || $logdata->action == 'GetValue')
1987  {
1988  $logtpl->setCurrentBlock($logdata->action);
1989  $logtpl->setVariable("ACTION", $logdata->action);
1990  $logtpl->setVariable("TIMESPAN", $logdata->timespan);
1991  $logtpl->setVariable("KEY", $logdata->key);
1992  $logtpl->setVariable("VALUE", $logdata->value);
1993  $logtpl->setVariable("RESULT", $logdata->result);
1994  $logtpl->setVariable("ERRORCODE", $errorcode);
1995  $debugfields=$this->getDebugValues(true);
1996  $importantkey=0;
1997  for ($i=0; $i <count($debugfields) ; $i++){
1998  if ($logdata->key == $debugfields[$i]) $importantkey=1;
1999  }
2000  $logtpl->setVariable("IMPORTANTKEY", "".$importantkey);
2001  $logtpl->setVariable("COLOR", $color);
2002  $logtpl->parseCurrentBlock();
2003  }
2004  else if ($logdata->action != 'INFO' && $logdata->action != 'ANALYZE' && $logdata->action != 'ANALYZETEST' && $logdata->action != 'SUMMARY' && $logdata->action != 'COMMENT' && $logdata->action != 'GetDiagnostic' && $logdata->action != 'GetLastError')
2005  {
2006  $logtpl->setCurrentBlock("defaultCall");
2007  $logtpl->setVariable("ACTION", $logdata->action);
2008  $logtpl->setVariable("TIMESPAN", $logdata->timespan);
2009  $logtpl->setVariable("KEY", $logdata->key);
2010  $logtpl->setVariable("VALUE", $logdata->value);
2011  $logtpl->setVariable("RESULT", $logdata->result);
2012  $logtpl->setVariable("ERRORCODE", $errorcode);
2013  $logtpl->setVariable("IMPORTANTKEY", "".$importantkey);
2014  $logtpl->setVariable("COLOR", $color);
2015  $logtpl->parseCurrentBlock();
2016  }
2017 
2018  /*
2019  if ($sqlwrite == true) {
2020  $ilLog->write("SQL WRITE");
2021  $logtpl->setCurrentBlock("SqlLog");
2022  $logtpl->setVariable("SQL_STRING", $sql_text);
2023  $logtpl->parseCurrentBlock();
2024  }
2025  */
2026 
2027  //create summary
2028  if ($logdata->action == "SUMMARY") {
2029  $this->createSummary($tmp_content);
2030  }
2031 
2032  fwrite($fh_txt,$logtpl->get());
2033  fclose($fh_txt);
2034  fclose($fh_csv);
2035  }
2036 
2037  private function getStructureFlat($data)
2038  {
2039  for ($i=0; $i <count($data) ; $i++) {
2040  $element = array();
2041  $element['title'] = $data[$i]['title'];
2042  $element['id'] = $data[$i]['id'];
2043  if ($data[$i]['sco'] == 1) {
2044  $element['sco'] = "sco";
2045  } else {
2046  $element['sco'] = "assset";
2047  }
2048  if ( $data[$i]['href'] !=null ) {
2049  array_push($this->flat_structure,$element);
2050  }
2051  if ($data[$i]['item']!=null) {
2052  $this->getStructureFlat($data[$i]['item']);
2053  }
2054  }
2055  }
2056 
2057  private function createSummary($api_data)
2058  {
2059  global $ilDB;
2060 
2061  $csv_data = null;
2062  //csv columns
2063  $columns_fixed = array('id','title','type','attempted');
2064 
2065  $ini_data = parse_ini_file("./Modules/Scorm2004/scripts/rtemain/debug_default.ini",true);
2066  $ini_array = $ini_data['summary'];
2067  $colums_variable = array();
2068  $api_keys = array();
2069 
2070  foreach ($ini_array as $key => $value) {
2071  if ($value == 1) {
2072  array_push($colums_variable,$key);
2073  array_push($api_keys,$key);
2074  array_push($colums_variable,"Status");
2075  }
2076  }
2077 
2078  $header_array = array_merge($columns_fixed, $colums_variable);
2079 
2080  $csv_header = implode(";",$header_array);
2081 
2082  //get strcuture
2083  $res = $ilDB->queryF(
2084  'SELECT jsdata FROM cp_package WHERE obj_id = %s',
2085  array('integer'),
2086  array($this->packageId)
2087  );
2088 
2089  $packageData = $ilDB->fetchAssoc($res);
2090 
2091  $structure = json_decode($packageData['jsdata'],true);
2092 
2093 
2094  $this->flat_structure = array(); //used for recursion
2095  $this->getStructureFlat($structure['item']['item']);
2096 
2097  foreach ($this->flat_structure as $tree_element) {
2098 
2099  $csv_data = $csv_data.$tree_element['id'].";".$tree_element['title'].";".$tree_element['sco'].";";
2100  if ($api_data[$tree_element['id']] != null) {
2101  $csv_data = $csv_data."X".";";
2102  } else {
2103  $csv_data = $csv_data.";";
2104  }
2105 
2106  //write api data
2107  $id = $tree_element['id'];
2108  foreach ($api_keys as $api_element) {
2109  if ($api_data[$id]!=null) {
2110  if ($api_data[$id][$api_element]!=null) {
2111  $csv_data = $csv_data.$api_data[$id][$api_element]['value'].";".$api_data[$id][$api_element]['status'].";";
2112  } else {
2113  $csv_data = $csv_data.";;";
2114  }
2115  }
2116  }
2117  $csv_data = $csv_data."\n";
2118  }
2119 
2120  $fh = fopen($this->summaryFileName(),"w");
2121  fwrite($fh,$csv_header."\n".$csv_data);
2122  fclose($fh);
2123  unlink($this->logTmpName());
2124  }
2129  function get_last_visited($a_obj_id, $a_user_id)
2130  {
2131  global $ilDB;
2132  $val_set = $ilDB->queryF('SELECT last_visited FROM sahs_user WHERE obj_id = %s AND user_id = %s',
2133  array('integer','integer'),
2134  array($a_obj_id,$a_user_id));
2135 
2136  $val_rec = $ilDB->fetchAssoc($val_set);
2137  return $val_rec["last_visited"];
2138  }
2139 }
2140 
2141 function datecmp($a, $b){
2142  if (strtotime($a['date']) == strtotime($b['date'])) {
2143  return 0;
2144  }
2145  return (strtotime($a['date']) < strtotime($b['date'])) ? 1 :-1;
2146 }
2147 
2148 ?>
get_last_visited($a_obj_id, $a_user_id)
functions for last_visited_sco
persistCMIData($userId=null, $packageId, $defaultLessonMode, $comments, $interactions, $objectives, $data=null)
ILIAS Setting Class.
exit
Definition: login.php:54
& executeCommand()
execute command
getDebugValues($test_sco=false)
$result
get_actual_attempts()
Get number of actual attempts for the user.
normalizeFields($table, &$node)
maps API data structure type to internal datatype on a node and accepts only valid values...
static getStyleSheetLocation($mode="output", $a_css_name="", $a_css_location="")
get full style sheet file name (path inclusive) of current user
$_GET["client_id"]
getInlineCSS()
Get inline css.
$_COOKIE["ilClientId"]
Definition: cron.php:11
$cmd
Definition: sahs_server.php:35
scormPlayerUnload($userId=null, $packageId)
createSummary($api_data)
getLogFileList($s_delete, $s_download, $s_open)
getCMIData($userId, $packageId)
static getMimeType($a_file)
get mime type for file
static _lookupObjectId($a_ref_id)
lookup object id
writeSharedData($sco_node_id)
global $ilCtrl
Definition: ilias.php:18
const ILIAS_WEB_DIR
fetchAssoc($a_set)
Fetch row as associative array from result set.
getCookie()
getting and setting Scorm2004 cookie Cookie contains enrypted associative array of sahs_lm...
readFile($path)
Try to find file, identify content type, write it to buffer, and stop immediatly If no file given...
$GLOBALS['ct_recipient']
static getImagePath($img, $module_path="", $mode="output", $offline=false)
get image path (for images located in a template directory)
getNodeData($sco_id, $fh)
special template class to simplify handling of ITX/PEAR
get_max_attempts($a_packageId)
Get max.
redirection script todo: (a better solution should control the processing via a xml file) ...
getMimetype($filename)
estimate content type for a filename by extension first do it for common static web files from extern...
static getIdleValue($fixedMode=false)
Returns the idle time in seconds.
$filename
Definition: buildRTE.php:89
static makeDir($a_dir)
creates a new directory and inherits all filesystem permissions of the parent directory You may pass ...
foreach($mandatory_scripts as $file) $timestamp
Definition: buildRTE.php:81
static getLocalPath($a_name="")
Get local path of a YUI js file.
increase_attemptAndsave_module_version()
Increases attempts by one and saves module_version for this package.
while($lm_rec=$ilDB->fetchAssoc($lm_set)) $data
global $ilUser
Definition: imgupload.php:15
$lm_set
datecmp($a, $b)
global $ilSetting
Definition: privfeed.php:40
Class ilObjSCORM2004LearningModule.
global $lng
Definition: privfeed.php:40
$path
Definition: index.php:22
get_max_attempts()
Get max.
readSharedData($sco_node_id)
if($_REQUEST['ilias_path']) define('ILIAS_HTTP_PATH' $_REQUEST['ilias_path']
Definition: index.php:7
quoteJSONArray($a_array)
getStatus($a_packageId, $a_user_id)