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