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