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