ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
class.ilSCORMOfflineMode.php
Go to the documentation of this file.
1<?php
2/* Copyright (c) 1998-2011 ILIAS open source, Extended GPL, see docs/LICENSE */
3//require_once "./Services/Object/classes/class.ilObject.php";
4
17{
18 public $type;
19 public $obj_id;
21 public $cmd_url;
25 public $som_url;
26
27 public $sop_dir;
28 public $som_dir;
30
31 public $sop_index;
33 public $lm_dir;
34 public $lm_index;
38 public $debug = false; // omit caching sop and som files for debugging
39
46 public function __construct()
47 {
48 global $DIC;
49 $ilias = $DIC['ilias'];
50 $this->ilias = $ilias;
51 $this->id = $_GET['ref_id'];
52 $this->obj_id = ilObject::_lookupObjectId($_GET['ref_id']);
53 include_once "./Modules/ScormAicc/classes/class.ilObjSAHSLearningModule.php";
54 $this->type = ilObjSAHSLearningModule::_lookupSubType($this->obj_id);
55 $this->cmd_url = './ilias.php?baseClass=ilSAHSPresentationGUI&cmd=';
56 $this->lm_cmd_url = './ilias.php?baseClass=ilSAHSPresentationGUI&ref_id=' . $this->id . '&cmd=';
57 $this->lm_info_url = $this->lm_cmd_url . 'infoScreen';
58 $this->player12_url = $this->cmd_url . 'offlineMode_player12';
59 $this->player2004_url = $this->cmd_url . 'offlineMode_player2004';
60 $this->som_url = $this->cmd_url . 'offlineMode_som';
61 $this->offlineMode = 'online';
62 $this->sop_index = './Modules/ScormAicc/sop/sop_index.html';
63 $this->sop_appcache = './Modules/ScormAicc/sop/sop.appcache';
64 $this->sop_dir = './Modules/ScormAicc/templates/sop/';
65 $this->som_dir = './Modules/ScormAicc/templates/som/';
66 $this->scripts_dir = './Modules/ScormAicc/scripts/';
67 $this->images_dir = './templates/default/images/scorm/';
68 $this->pouchdb_js = './libs/bower/bower_components/pouchdb/dist/pouchdb.min.js';
69 $this->jquery_js = './libs/bower/bower_components/jquery/dist/jquery.min.js';
70 $this->bootstrap_js = './libs/bower/bower_components/bootstrap/dist/js/bootstrap.min.js';
71 $this->bootstrap_css = './libs/bower/bower_components/bootstrap/dist/css/bootstrap.min.css';
72 $this->read();
73 }
74
75 public function getSopManifestEntries()
76 {
77 global $DIC;
78 $log = $DIC['log'];
79 $log->write("getSopManifestEntries ");
80 $manifest_string = "";
81 if (!$this->debug) {
82 // if ($this->type == "scorm2004") {
83 $BASE_DIR = './Modules/Scorm2004/';
84 $manifest_string .= ilUtil::getImagePath("scorm/asset.svg", false) . "\n";
85 $manifest_string .= ilUtil::getImagePath("scorm/completed.svg", false) . "\n";
86 $manifest_string .= ilUtil::getImagePath("scorm/not_attempted.svg", false) . "\n";
87 $manifest_string .= ilUtil::getImagePath("scorm/running.svg", false) . "\n";
88 $manifest_string .= ilUtil::getImagePath("scorm/incomplete.svg", false) . "\n";
89 $manifest_string .= ilUtil::getImagePath("scorm/passed.svg", false) . "\n";
90 $manifest_string .= ilUtil::getImagePath("scorm/failed.svg", false) . "\n";
91 // $manifest_string .= ilUtil::getImagePath("scorm/browsed.svg",false) . "\n";
92 $manifest_string .= ilUtil::getStyleSheetLocation() . "\n";
93 $manifest_string .= $BASE_DIR . 'templates/default/player.css' . "\n";
94 $manifest_string .= $BASE_DIR . 'scripts/buildrte/rte.js' . "\n";
95 $manifest_string .= $BASE_DIR . 'scripts/ilNestedList.js' . "\n";
96 $manifest_string .= iljQueryUtil::getLocaljQueryPath() . "\n";
97 $manifest_string .= $this->player2004_url . "\n";
98 // } else {
99 $manifest_string .= $this->player12_url . "\n";
100 // }
101 $manifest_string .= $this->som_url . "\n";
102 // $log->write("Manifest: ".$manifest_string);
103 $objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->sop_dir));
104 foreach ($objects as $name => $object) {
105 if (preg_match('/\/\.+/', $name)) {
106 continue;
107 }
108 //$manifest_string .= preg_replace('/^\./','./Modules/ScormAicc',$name) . "\n"; // for cli
109 $manifest_string .= self::encodeuri($name) . "\n";
110 }
111 $objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->som_dir));
112 foreach ($objects as $name => $object) {
113 if (preg_match('/\/\.+/', $name)) {
114 continue;
115 }
116 //$manifest_string .= preg_replace('/^\./','./Modules/ScormAicc',$name) . "\n"; // for cli
117 $manifest_string .= self::encodeuri($name) . "\n";
118 }
119
120 $objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->scripts_dir));
121 foreach ($objects as $name => $object) {
122 if (preg_match('/\/\.+/', $name)) { //UK statt .+ .js und SCORM-Scripts weg
123 continue;
124 }
125 //$manifest_string .= preg_replace('/^\./','./Modules/ScormAicc',$name) . "\n"; // for cli
126 $manifest_string .= self::encodeuri($name) . "\n";
127 }
128 $objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->images_dir));
129 foreach ($objects as $name => $object) {
130 if (preg_match('/\/\.+/', $name)) {
131 continue;
132 }
133 //$manifest_string .= preg_replace('/^\./','./Modules/ScormAicc',$name) . "\n"; // for cli
134 $manifest_string .= self::encodeuri($name) . "\n";
135 }
136
137 $manifest_string .= $this->pouchdb_js . "\n";
138 $manifest_string .= $this->jquery_js . "\n";
139 $manifest_string .= $this->bootstrap_js . "\n";
140 $manifest_string .= $this->bootstrap_css . "\n";
141 }
142 //$log->write($manifest_string);
143 return $manifest_string;
144 }
145
146 public function getLmManifestEntries()
147 { // ToDo: database support !!
148 global $DIC;
149 $log = $DIC['log'];
150 $log->write("getLmManifestEntries");
151 $this->lm_dir = ilUtil::getWebspaceDir("filesystem") . '/lm_data/lm_' . $this->obj_id;
152 $manifest_string = "";
153 $objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->lm_dir));
154 foreach ($objects as $name => $object) {
155 if (preg_match('/\/\.+/', $name)) {
156 continue;
157 }
158 if (preg_match('/\.zip$/', $name)) {
159 continue;
160 }
161 //$manifest_string .= preg_replace('/^\./','./Modules/ScormAicc',$name) . "\n"; // for cli
162 $manifest_string .= self::encodeuri($name) . "\n";
163 }
164 //$log->write($manifest_string);
165 return $manifest_string;
166 }
167
168 // function il2sop() {
169 public function tracking2sop()
170 {
171 global $DIC;
172 $ilUser = $DIC['ilUser'];
173 $ilias = $DIC['ilias'];
174 // $this->setOfflineMode("il2sop");
175 header('Content-Type: text/javascript; charset=UTF-8');
176
177 include_once "./Modules/ScormAicc/classes/class.ilObjSAHSLearningModule.php";
178 $ob = new ilObjSAHSLearningModule($this->id);
179 $module_version = $ob->getModuleVersion();
180 $sahs_user = $this->il2sopSahsUser();
181 $support_mail = "";//TODO
182 $scorm_version = "1.2";
183 if ($this->type == "scorm2004") {
184 $scorm_version = "2004";
185 }
186 $tree = "";
187
188 $learning_progress_enabled = 1;
189 include_once './Services/Object/classes/class.ilObjectLP.php';
190 $olp = ilObjectLP::getInstance($this->obj_id);
191 if ($olp->getCurrentMode() == 0) {
192 $learning_progress_enabled = 0;
193 }
194
195 $certificate_enabled = 0;
196
197 $adlact_data = null;
198 $ilias_version = $ilias->getSetting("ilias_version");
199
200 if ($this->type == 'scorm2004') {
201 include_once "./Modules/Scorm2004/classes/ilSCORM13Player.php";
202 $ob2004 = new ilSCORM13Player();
203 $init_data = json_encode($ob2004->getConfigForPlayer());
204 $resources = json_decode($ob2004->getCPDataInit());
205 $cmi = $ob2004->getCMIData($ilUser->getID(), $this->obj_id);
206 $max_attempt = $ob2004->get_max_attempts();
207 $adlact_data = json_decode($ob2004->getADLActDataInit());
208 //$globalobj_data = $ob2004->readGObjectiveInit();
209 } else {
210 include_once "./Modules/ScormAicc/classes/SCORM/class.ilObjSCORMInitData.php";
211 $slm_obj = new ilObjSCORMLearningModule($_GET["ref_id"]);
212 $init_data = ilObjSCORMInitData::getIliasScormVars($slm_obj);
213 $resources = json_decode(ilObjSCORMInitData::getIliasScormResources($this->obj_id));
214 $tree = json_decode(ilObjSCORMInitData::getIliasScormTree($this->obj_id));
215 $cmi = json_decode(ilObjSCORMInitData::getIliasScormData($this->obj_id));
216 $max_attempt = ilObjSCORMInitData::get_max_attempts($this->obj_id);
217 }
218 //UK max_attempt weg!
219 // if ($max_attempt == null) $max_attempt = 0;
220 $result = array(
221 'client_data' => array(
222 $support_mail
223 ),
224 'user_data' => $this->il2sopUserData(),
225 'lm' => array(
226 ilObject::_lookupTitle($this->obj_id),
227 ilObject::_lookupDescription($this->obj_id),
228 $scorm_version,
229 1,//active
230 $init_data,
231 $resources,
232 $tree,
233 $module_version,
234 "", //offline_zip_created!!!!!!!!
235 $learning_progress_enabled,
236 $certificate_enabled,
237 $max_attempt,
238 $adlact_data,
239 $ilias_version
240 ),
241 'sahs_user' => $sahs_user,
242 'cmi' => $cmi
243 );
244
245 print(json_encode($result));
246 }
247
248 public function getClientIdSop()
249 {
250 $iliasDomain = substr(ILIAS_HTTP_PATH, 7);
251 if (substr($iliasDomain, 0, 1) == "\/") {
252 $iliasDomain = substr($iliasDomain, 1);
253 }
254 if (substr($iliasDomain, 0, 4) == "www.") {
255 $iliasDomain = substr($iliasDomain, 4);
256 }
257 return $iliasDomain . ';' . CLIENT_ID;
258 }
259
260 public function il2sopUserData()
261 {
262 global $DIC;
263 $ilUser = $DIC['ilUser'];
264 return array(
265 $ilUser->getLogin(),
266 "",
267 $ilUser->getFirstname(),
268 $ilUser->getLastname(),
269 $ilUser->getUTitle(),
270 $ilUser->getGender(),
271 $ilUser->getID()
272 );
273 }
274 public function il2sopSahsUser()
275 {
276 global $DIC;
277 $ilDB = $DIC['ilDB'];
278 $ilUser = $DIC['ilUser'];
279 $package_attempts = 0;
280 $module_version = 1;//if module_version in sop is different...
281 $last_visited = "";
282 $first_access = null;
283 $last_access = null;
284 $last_status_change = null;
285 $total_time_sec = null;
286 $sco_total_time_sec = 0;
287 $status = 0;
288 $percentage_completed = 0;
289 $user_data = "";
290
291 global $DIC;
292 $ilDB = $DIC['ilDB'];
293 $ilUser = $DIC['ilUser'];
294 $res = $ilDB->queryF(
295 'SELECT * FROM sahs_user WHERE obj_id=%s AND user_id=%s',
296 array('integer','integer'),
297 array($this->obj_id,$ilUser->getID())
298 );
299 while ($row = $ilDB->fetchAssoc($res)) {
300 $package_attempts = $row['package_attempts'];
301 $module_version = $row['module_version'];
302 $last_visited = $row['last_visited'];
303 if ($row['first_access'] != null) {
304 $first_access = strtotime($row['first_access']) * 1000;//check Oracle!
305 }
306 if ($row['last_access'] != null) {
307 $last_access = strtotime($row['last_access']) * 1000;//check Oracle!
308 }
309 $total_time_sec = $row['total_time_sec'];
310 $sco_total_time_sec = $row['sco_total_time_sec'];
311 $status = $row['status'];
312 $percentage_completed = $row['percentage_completed'];
313 }
314 if ($first_access == null) {
315 include_once './Services/Tracking/classes/class.ilChangeEvent.php';
316 $all = ilChangeEvent::_lookupReadEvents($this->obj_id, $ilUser->getID());
317 foreach ($all as $event) {
318 $first_access = strtotime($event['first_access']) * 1000;//
319 }
320 }
321 return array($package_attempts, $module_version, $last_visited, $first_access, $last_access, $last_status_change, $total_time_sec, $sco_total_time_sec, $status, $percentage_completed, $user_data);
322 }
323
324 public function sop2il()
325 {
326 // sleep(5);
327 global $DIC;
328 $ilDB = $DIC['ilDB'];
329 $ilUser = $DIC['ilUser'];
330 $in = file_get_contents("php://input");
331 $GLOBALS['DIC']['ilLog']->write($in);
332 $ret = array('msg' => array(),'err' => array());
333
334 if (!$in || $in == "") {
335 $ret['err'][] = "no post data recieved";
336 print(json_encode($ret));
337 exit;
338 }
339 $userId = $ilUser->getID();
340 $result = true;
341
342 if ($this->type == 'scorm2004') {
343 $lm_set = $ilDB->queryF('SELECT default_lesson_mode, interactions, objectives, comments, time_from_lms FROM sahs_lm WHERE id = %s', array('integer'), array($this->obj_id));
344 while ($lm_rec = $ilDB->fetchAssoc($lm_set)) {
345 $defaultLessonMode = ($lm_rec["default_lesson_mode"]);
346 $interactions = (ilUtil::yn2tf($lm_rec["interactions"]));
347 $objectives = (ilUtil::yn2tf($lm_rec["objectives"]));
348 $comments = (ilUtil::yn2tf($lm_rec["comments"]));
349 $time_from_lms = (ilUtil::yn2tf($lm_rec["time_from_lms"]));
350 }
351 include_once './Modules/Scorm2004/classes/class.ilSCORM2004StoreData.php';
352 $data = json_decode($in);
353 $GLOBALS['DIC']['ilLog']->write('cmi_count=' . count($data->cmi));
354 for ($i = 0; $i < count($data->cmi); $i++) {
355 if ($result == true) {
356 //$a_r=array();
357 $cdata = $data->cmi[$i];
359 $userId,
360 $this->obj_id,
361 $data->cmi[$i],//json_decode($data->cmi[$i]),
362 $comments,
363 $interactions,
364 $objectives
365 );
366 if (!is_array($a_r)) {
367 $result = false;
368 }
369 }
370 }
371 if ($result == true) {
372 $result = ilSCORM2004StoreData::syncGlobalStatus($userId, $this->obj_id, $data, $data->now_global_status, $time_from_lms);
373 }
374 } else {
375 include_once "./Modules/ScormAicc/classes/SCORM/class.ilObjSCORMTracking.php";
376 $data = json_decode($in);
377 $result = ilObjSCORMTracking::storeJsApiCmi($userId, $this->obj_id, $data);
378 if ($result == true) {
379 $result = ilObjSCORMTracking::syncGlobalStatus($userId, $this->obj_id, $data, $data->now_global_status);
380 }
381 }
382 if ($result == true) {
383 $result = self::scormPlayerUnloadForSOP2il($data);
384 }
385
386 if ($result == false) {
387 $ret['err'][] = "invalid post data recieved";
388 } else {
389 $ret['msg'][] = "post data recieved";
390 }
391 header('Content-Type: text/plain; charset=UTF-8');
392 print json_encode($ret);
393 }
394
396 {
397 global $DIC;
398 $ilDB = $DIC['ilDB'];
399 $ilUser = $DIC['ilUser'];
400 $first_access = null;
401 if ($data->first_access != null) {
402 $first_access = date('Y-m-d H:i:s', round($data->first_access / 1000));
403 }
404 $last_access = null;
405 $i_last_access = null;
406 if ($data->last_access != null) {
407 $i_last_access = round($data->last_access / 1000);
408 $last_access = date('Y-m-d H:i:s', $i_last_access);
409 include_once("./Services/Tracking/classes/class.ilChangeEvent.php");
410 ilChangeEvent::_updateAccessForScormOfflinePlayer($this->obj_id, $ilUser->getId(), $i_last_access, $first_access);
411 }
412 $last_status_change = null;
413 if ($data->last_status_change != null) {
414 $last_status_change = date('Y-m-d H:i:s', round($data->last_status_change / 1000));
415 }
416 $GLOBALS['DIC']['ilLog']->write('first_access=' . $first_access);
417 $res = $ilDB->queryF(
418 'UPDATE sahs_user SET first_access=%s, last_access=%s, last_status_change=%s, last_visited=%s, module_version=%s WHERE obj_id=%s AND user_id=%s',
419 array('timestamp','timestamp','timestamp','text','integer','integer','integer'),
420 array($first_access,$last_access,$last_status_change,$data->last_visited,$data->module_version, $this->obj_id,$ilUser->getId())
421 );
422
423 //populate last_status_change
424 return true;
425 }
426
427 //offlineMode: offline, online, il2sop, sop2il
428 public function setOfflineMode($a_mode)
429 {
430 global $DIC;
431 $ilDB = $DIC['ilDB'];
432 $ilUser = $DIC['ilUser'];
433 $res = $ilDB->queryF(
434 'UPDATE sahs_user SET offline_mode=%s WHERE obj_id=%s AND user_id=%s',
435 array('text','integer','integer'),
436 array($a_mode, $this->obj_id,$ilUser->getId())
437 );
438 $this->offlineMode = $a_mode;
439 }
440 public function getOfflineMode()
441 {
442 return $this->offlineMode;
443 }
444
445 private function read()
446 {
447 global $DIC;
448 $ilDB = $DIC['ilDB'];
449 $ilUser = $DIC['ilUser'];
450 $res = $ilDB->queryF(
451 'SELECT offline_mode FROM sahs_user WHERE obj_id=%s AND user_id=%s',
452 array('integer','integer'),
453 array($this->obj_id,$ilUser->getId())
454 );
455 while ($row = $ilDB->fetchAssoc($res)) {
456 if ($row['offline_mode'] != null && $row['offline_mode'] != '') {
457 $this->offlineMode = $row['offline_mode'];
458 } else {
459 $this->offlineMode = "online";
460 }
461 }
462 }
463
464 public static function checkIfAnyoneIsInOfflineMode($obj_id)
465 {
466 global $DIC;
467 $ilDB = $DIC['ilDB'];
468 $res = $ilDB->queryF(
469 "SELECT count(*) cnt FROM sahs_user WHERE obj_id=%s AND offline_mode = 'offline'",
470 array('integer'),
471 array($obj_id)
472 );
473 $val_rec = $ilDB->fetchAssoc($res);
474 if ($val_rec["cnt"] == 0) {
475 return false;
476 }
477 return true;
478 }
479
480 public static function usersInOfflineMode($obj_id)
481 {
482 global $DIC;
483 $ilDB = $DIC['ilDB'];
484 $users = array();
485 $res = $ilDB->queryF(
486 "SELECT user_id, lastname, firstname FROM sahs_user, usr_data "
487 . "WHERE sahs_user.obj_id=%s AND sahs_user.offline_mode = 'offline' AND sahs_user.user_id=usr_data.usr_id",
488 array('integer'),
489 array($obj_id)
490 );
491 while ($row = $ilDB->fetchAssoc($res)) {
492 $users[] = $row;
493 }
494 return $users;
495 }
496
497 public static function stopOfflineModeForUser($obj_id, $user_id)
498 {
499 global $DIC;
500 $ilDB = $DIC['ilDB'];
501 $res = $ilDB->queryF(
502 "UPDATE sahs_user SET offline_mode='online' WHERE obj_id=%s AND user_id=%s",
503 array('integer','integer'),
504 array($obj_id,$user_id)
505 );
506 }
507
508 public static function encodeuri($path)
509 {
510 return implode('/', array_map('rawurlencode', explode('/', $path)));
511 }
512}
$result
if(!defined('PATH_SEPARATOR')) $GLOBALS['_PEAR_default_error_mode']
Definition: PEAR.php:64
if(php_sapi_name() !='cli') $in
Definition: Utf8Test.php:37
if(! $in) print
$_GET["client_id"]
An exception for terminatinating execution or to throw for unit testing.
static _updateAccessForScormOfflinePlayer($obj_id, $usr_id, $i_last_access, $t_first_access)
_updateAccessForScormOfflinePlayer needed to synchronize last_access and first_access when learning m...
static _lookupReadEvents($obj_id, $usr_id=null)
Reads all read events which occured on the object which happened after the last time the user caught ...
Class ilObjSCORMLearningModule.
static _lookupSubType($a_obj_id)
lookup subtype id (scorm, )
static getIliasScormData($a_packageId)
static getIliasScormVars($slm_obj)
static get_max_attempts($a_packageId)
Get max.
static getIliasScormResources($a_packageId)
static getIliasScormTree($a_packageId)
Class ilObjSCORMLearningModule.
static syncGlobalStatus($userId, $packageId, $data, $new_global_status)
static storeJsApiCmi($user_id, $obj_id, $data)
static getInstance($a_obj_id)
static _lookupTitle($a_id)
lookup object title
static _lookupObjectId($a_ref_id)
lookup object id
static _lookupDescription($a_id)
lookup object description
static setCMIData($userId, $packageId, $data, $getComments, $getInteractions, $getObjectives)
static syncGlobalStatus($userId, $packageId, $data, $new_global_status, $time_from_lms)
Class ilSCORMOfflineMode.
static stopOfflineModeForUser($obj_id, $user_id)
static checkIfAnyoneIsInOfflineMode($obj_id)
static usersInOfflineMode($obj_id)
static getWebspaceDir($mode="filesystem")
get webspace directory
static getStyleSheetLocation($mode="output", $a_css_name="", $a_css_location="")
get full style sheet file name (path inclusive) of current user
static yn2tf($a_yn)
convert "y"/"n" to true/false
static getImagePath($img, $module_path="", $mode="output", $offline=false)
get image path (for images located in a template directory)
static getLocaljQueryPath()
exit
Definition: login.php:29
if($format !==null) $name
Definition: metadata.php:230
$i
Definition: metadata.php:24
redirection script todo: (a better solution should control the processing via a xml file)
$ret
Definition: parser.php:6
$log
Definition: result.php:15
foreach($_POST as $key=> $value) $res
global $ilDB
$lm_set
$data
Definition: storeScorm.php:23
$ilUser
Definition: imgupload.php:18
$DIC
Definition: xapitoken.php:46