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
5require_once("./Services/YUI/classes/class.ilYuiUtil.php");
6require_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;
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
2091function 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}
sprintf('%.4f', $callTime)
date( 'd-M-Y', $objPHPExcel->getProperties() ->getCreated())
$result
if(! $in) print
foreach($mandatory_scripts as $file) $timestamp
Definition: buildRTE.php:81
$_GET["client_id"]
An exception for terminatinating execution or to throw for unit testing.
static getMimeType($a_file, $a_external=null)
get mime type for file
Class ilObjSCORM2004LearningModule.
static get_max_attempts($a_packageId)
Get max.
static getStatus($a_packageId, $a_user_id, $auto_last_visited, $scormType="1.2")
static _lookupObjectId($a_ref_id)
lookup object id
normalizeFields($table, &$node)
maps API data structure type to internal datatype on a node and accepts only valid values,...
getMimetype($filename)
estimate content type for a filename by extension first do it for common static web files from extern...
getDebugValues($test_sco=false)
increase_attemptAndsave_module_version()
Increases attempts by one and saves module_version for this package.
getLogFileList($s_delete, $s_download, $s_open)
getNodeData($sco_id, $fh)
getCMIData($userId, $packageId)
writeSharedData($sco_node_id)
createSummary($api_data)
readSharedData($sco_node_id)
get_max_attempts()
Get max.
quoteJSONArray($a_array)
& executeCommand()
execute command
get_actual_attempts()
Get number of actual attempts for the user.
static getInlineCSS()
Get inline css.
static persistCMIData($userId=null, $packageId, $defaultLessonMode, $comments, $interactions, $objectives, $time_from_lms, $data=null)
static scormPlayerUnload($userId=null, $packageId, $time_from_lms)
static getIdleValue($fixedMode=false)
Returns the idle time in seconds.
special template class to simplify handling of ITX/PEAR
static getStyleSheetLocation($mode="output", $a_css_name="", $a_css_location="")
get full style sheet file name (path inclusive) of current user
static getImagePath($img, $module_path="", $mode="output", $offline=false)
get image path (for images located in a template directory)
static makeDir($a_dir)
creates a new directory and inherits all filesystem permissions of the parent directory You may pass ...
static getCookieMaxLifetimeInSeconds()
static signFolderOfStartFile($start_file_path)
static getLocalPath($a_name="")
Get local path of a YUI js file.
static getLocaljQueryPath()
$key
Definition: croninfo.php:18
$i
Definition: disco.tpl.php:19
if(!array_key_exists('StateId', $_REQUEST)) $id
$GLOBALS['loaded']
Global hash that tracks already loaded includes.
datecmp($a, $b)
global $ilCtrl
Definition: ilias.php:18
global $lng
Definition: privfeed.php:17
global $ilSetting
Definition: privfeed.php:17
$query
if(empty($password)) $table
Definition: pwgen.php:24
global $ilErr
Definition: raiseError.php:16
foreach($_POST as $key=> $value) $res
$packageId
global $ilDB
if((!isset($_SERVER['DOCUMENT_ROOT'])) OR(empty($_SERVER['DOCUMENT_ROOT']))) $_SERVER['DOCUMENT_ROOT']
$ilUser
Definition: imgupload.php:18
$params
Definition: disable.php:11