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
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 $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
2134function 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}
$result
if(! $in) print
$path
Definition: aliased.php:25
exit
Definition: backend.php:16
$filename
Definition: buildRTE.php:89
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
datecmp($a, $b)
global $ilCtrl
Definition: ilias.php:18
$config
Definition: bootstrap.php:15
$row
global $ilSetting
Definition: privfeed.php:17
$query
if(empty($password)) $table
Definition: pwgen.php:24
$ilErr
Definition: raiseError.php:18
global $DIC
Definition: saml.php:7
$lng
foreach($_POST as $key=> $value) $res
$packageId
global $ilDB
if((!isset($_SERVER['DOCUMENT_ROOT'])) OR(empty($_SERVER['DOCUMENT_ROOT']))) $_SERVER['DOCUMENT_ROOT']
$values
$ilUser
Definition: imgupload.php:18
$data
Definition: bench.php:6