ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
class.ilSCORM2004StoreData.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
13{
14
15 public function scormPlayerUnload($userId=null, $packageId, $time_from_lms)
16 {
17 global $ilDB;
18
19 $data = json_decode(is_string($data) ? $data : file_get_contents('php://input'));
20 if (!$data) return;
21 if ($userId == null) {
22 $userId=(int) $data->p;
23 self::checkIfAllowed($packageId,$userId,$data->hash);
24 }
25 $last_visited = "";
26 if ($data->last !="") $last_visited = $data->last;
27 $endDate = date('Y-m-d H:i:s', mktime(date('H'), date('i')+5, date('s'), date('m'), date('d'), date('Y')));
28 $total_time_sec = null;
29 if ($data->total_time_sec !="") {
30 $total_time_sec = $data->total_time_sec;
31 $ilDB->manipulateF('UPDATE sahs_user
32 SET total_time_sec = %s, last_visited = %s, hash_end =%s, last_access = %s
33 WHERE obj_id = %s AND user_id = %s',
34 array('integer', 'text', 'timestamp', 'timestamp', 'integer', 'integer'),
35 array($total_time_sec,$last_visited, $endDate, date('Y-m-d H:i:s'), $packageId, $userId)
36 );
37 if ($time_from_lms==true) {
38 self::ensureObjectDataCacheExistence();
39 global $ilObjDataCache;
40 // sync access number and time in read event table
41 include_once("./Modules/Scorm2004/classes/class.ilSCORM2004Tracking.php");
42 ilSCORM2004Tracking::_syncReadEvent($packageId, $userId, "sahs", (int)$_GET['ref_id'], $time_from_lms);
43 //end sync access number and time in read event table
44 }
45 } else {
46 $ilDB->manipulateF('UPDATE sahs_user
47 SET last_visited = %s, hash_end =%s, last_access = %s
48 WHERE obj_id = %s AND user_id = %s',
49 array('text', 'timestamp', 'timestamp', 'integer', 'integer'),
50 array($last_visited, $endDate, date('Y-m-d H:i:s'), $packageId, $userId)
51 );
52 }
53
54 header('Content-Type: text/plain; charset=UTF-8');
55 print("");
56 }
57
58
59 public function persistCMIData($userId=null, $packageId, $defaultLessonMode, $comments, $interactions, $objectives, $time_from_lms, $data = null)
60 {
61 global $ilLog;
62
63 if ($defaultLessonMode == "browse") {return;}
64
65 $jsMode = strpos($_SERVER['HTTP_ACCEPT'], 'text/javascript')!==false;
66
67 $data = json_decode(is_string($data) ? $data : file_get_contents('php://input'));
68 $ilLog->write("dataTo_setCMIData: ".file_get_contents('php://input'));
69 if (!$data) return;
70 if ($userId == null) {
71 $userId=(int) $data->p;
72 self::checkIfAllowed($packageId,$userId,$data->hash);
73// header('Access-Control-Allow-Origin: http://localhost:50012');//just for tests - not for release UK
74 }
75 $return = array();
77 $userId,
79 $data,
80 $comments,
81 $interactions,
82 $objectives
83 );
84
85 //$new_global_status=ilSCORM2004StoreData::setGlobalObjectivesAndGetGlobalStatus($userId, $packageId, $data);
87 $new_global_status = $data->now_global_status;
88 $return["new_global_status"] = $new_global_status;
89
90 ilSCORM2004StoreData::syncGlobalStatus($userId, $packageId, $data, $new_global_status, $time_from_lms);
91
92 $ilLog->write("SCORM: return of persistCMIData: ".json_encode($return));
93 if ($jsMode)
94 {
95 header('Content-Type: text/javascript; charset=UTF-8');
96 print(json_encode($return));
97 }
98 else
99 {
100 header('Content-Type: text/html; charset=UTF-8');
101 print(var_export($return, true));
102 }
103 }
104
105 function checkIfAllowed($packageId,$userId,$hash){
106 global $ilDB;
107 $res = $ilDB->queryF('select hash from sahs_user where obj_id=%s AND user_id=%s AND hash_end>%s',
108 array('integer','integer','timestamp'),
109 array($packageId,$userId,date('Y-m-d H:i:s'))
110 );
111 $rowtmp=$ilDB->fetchAssoc($res);
112 if ($rowtmp['hash']==$hash) return;
113 else die("not allowed");
114 }
115
116 public function setCMIData($userId, $packageId, $data,$getComments,$getInteractions,$getObjectives) {
117 global $ilDB, $ilLog;
118
119 $result = array();
120
121 if (!$data) return $result;
122
123 $i_check=$data->i_check;
124 $i_set=$data->i_set;
125 $b_node_update=false;
126 $cmi_node_id=null;
127 $a_map_cmi_interaction_id=array();
128
129 $tables = array('node', 'comment', 'interaction', 'objective', 'correct_response');
130
131 foreach($tables as $table)
132 {
133 if (!is_array($data->$table)) continue;
134
135 $ilLog->write("SCORM: setCMIData, table -".$table."-");
136
137 // now iterate through data rows from input
138 foreach($data->$table as &$row)
139 {
140 $ilLog->write("Checking table: ".$table);
141
142 switch($table)
143 {
144 case 'node': //is always first and has only 1 row
145
146 $res = $ilDB->queryF(
147 'SELECT cmi_node_id FROM cmi_node WHERE cp_node_id = %s and user_id = %s',
148 array('integer','integer'),
149 array($row[19],$userId)
150 );
151 $rowtmp=$ilDB->fetchAssoc($res);
152 $cmi_node_id=$rowtmp['cmi_node_id'];
153 if ($cmi_node_id!=null) $b_node_update=true;
154 else {
155 $cmi_node_id = $ilDB->nextId('cmi_node');
156 $b_node_update=false;
157 }
158 $ilLog->write("setCMIdata with cmi_node_id = ".$cmi_node_id);
159 $a_data=array(
160 'accesscount' => array('integer', $row[0]),
161 'accessduration' => array('text', $row[1]),
162 'accessed' => array('text', $row[2]),
163 'activityabsduration' => array('text', $row[3]),
164 'activityattemptcount' => array('integer', $row[4]),
165 'activityexpduration' => array('text', $row[5]),
166 'activityprogstatus' => array('integer', $row[6]),
167 'attemptabsduration' => array('text', $row[7]),
168 'attemptcomplamount' => array('float', $row[8]),
169 'attemptcomplstatus' => array('integer', $row[9]),
170 'attemptexpduration' => array('text', $row[10]),
171 'attemptprogstatus' => array('integer', $row[11]),
172 'audio_captioning' => array('integer', $row[12]),
173 'audio_level' => array('float', $row[13]),
174 'availablechildren' => array('text', $row[14]),
175 'cmi_node_id' => array('integer', $cmi_node_id),
176 'completion' => array('float', $row[16]),
177 'completion_status' => array('text', $row[17]),
178 'completion_threshold' => array('text', $row[18]),
179 'cp_node_id' => array('integer', $row[19]),
180 'created' => array('text', $row[20]),
181 'credit' => array('text', $row[21]),
182 'delivery_speed' => array('float', $row[22]),
183 'c_entry' => array('text', $row[23]),
184 'c_exit' => array('text', $row[24]),
185 'c_language' => array('text', $row[25]),
186 'launch_data' => array('clob', $row[26]),
187 'learner_name' => array('text', $row[27]),
188 'location' => array('text', $row[28]),
189 'c_max' => array('float', $row[29]),
190 'c_min' => array('float', $row[30]),
191 'c_mode' => array('text', $row[31]),
192 'modified' => array('text', $row[32]),
193 'progress_measure' => array('float', $row[33]),
194 'c_raw' => array('float', $row[34]),
195 'scaled' => array('float', $row[35]),
196 'scaled_passing_score' => array('float', $row[36]),
197 'session_time' => array('text', $row[37]),
198 'success_status' => array('text', $row[38]),
199 'suspend_data' => array('clob', $row[39]),
200 'total_time' => array('text', $row[40]),
201 'user_id' => array('integer', $userId),
202 'c_timestamp' => array('timestamp', date('Y-m-d H:i:s')),
203 'additional_tables' => array('integer', $i_check)
204 );
205
206 if($b_node_update==false) {
207 $ilLog->write("Want to insert row: ".count($row) );
208 $ilDB->insert('cmi_node', $a_data);
209 } else {
210 $ilDB->update('cmi_node', $a_data, array('cmi_node_id' => array('integer', $cmi_node_id)));
211 $ilLog->write("updated");
212 }
213
214 if($b_node_update==true) {
215 //remove
216 if ($i_set>7) {
217 $i_set-=8;
218 if ($getComments) {
219 $q = 'DELETE FROM cmi_comment WHERE cmi_node_id = %s';
220 $ilDB->manipulateF($q, array('integer'), array($cmi_node_id));
221 }
222 }
223 if ($i_set>3) {
224 $i_set-=4;
225 if ($getInteractions) {
226 $q = 'DELETE FROM cmi_correct_response
227 WHERE cmi_interaction_id IN (
228 SELECT cmi_interaction.cmi_interaction_id FROM cmi_interaction WHERE cmi_interaction.cmi_node_id = %s)';
229 $ilDB->manipulateF($q, array('integer'), array($cmi_node_id));
230 }
231 }
232 if ($i_set>1) {
233 $i_set-=2;
234 if ($getInteractions) {
235 $q = 'DELETE FROM cmi_interaction WHERE cmi_node_id = %s';
236 $ilDB->manipulateF($q, array('integer'), array($cmi_node_id));
237 }
238 }
239 if ($i_set>0) {
240 $i_set=0;
241 if ($getObjectives) {
242 $q = 'DELETE FROM cmi_objective WHERE cmi_node_id = %s';
243 $ilDB->manipulateF($q, array('integer'), array($cmi_node_id));
244 }
245 }
246 //end remove
247 }
248 //to send to client
249 $result[(string)$row[19]] = $cmi_node_id;
250 break;
251
252 case 'comment':
253 $row[0] = $ilDB->nextId('cmi_comment');
254
255 $ilDB->insert('cmi_comment', array(
256 'cmi_comment_id' => array('integer', $row[0]),
257 'cmi_node_id' => array('integer', $cmi_node_id),
258 'c_comment' => array('clob', $row[2]),
259 'c_timestamp' => array('text', $row[3]),
260 'location' => array('text', $row[4]),
261 'sourceislms' => array('integer', $row[5])
262 ));
263 break;
264
265 case 'interaction':
266 $cmi_interaction_id = $ilDB->nextId('cmi_interaction');
267 $a_map_cmi_interaction_id[]=array($row[0],$cmi_interaction_id);
268 $ilDB->insert('cmi_interaction', array(
269 'cmi_interaction_id' => array('integer', $cmi_interaction_id),
270 'cmi_node_id' => array('integer', $cmi_node_id),
271 'description' => array('clob', $row[2]),
272 'id' => array('text', $row[3]),
273 'latency' => array('text', $row[4]),
274 'learner_response' => array('clob', $row[5]),
275 'result' => array('text', $row[6]),
276 'c_timestamp' => array('text', $row[7]),
277 'c_type' => array('text', $row[8]),
278 'weighting' => array('float', $row[9])
279 ));
280 break;
281
282 case 'objective':
283 $row[2] = $ilDB->nextId('cmi_objective');
284 $cmi_interaction_id = null;
285 if ($row[0] != null) {
286 for($i=0;$i<count($a_map_cmi_interaction_id);$i++)
287 if ($row[0] == $a_map_cmi_interaction_id[$i][0]) $cmi_interaction_id=$a_map_cmi_interaction_id[$i][1];
288 }
289 $ilDB->insert('cmi_objective', array(
290 'cmi_interaction_id' => array('integer', $cmi_interaction_id),
291 'cmi_node_id' => array('integer', $cmi_node_id),
292 'cmi_objective_id' => array('integer', $row[2]),
293 'completion_status' => array('text', $row[3]),
294 'description' => array('clob', $row[4]),
295 'id' => array('text', $row[5]),
296 'c_max' => array('float', $row[6]),
297 'c_min' => array('float', $row[7]),
298 'c_raw' => array('float', $row[8]),
299 'scaled' => array('float', $row[9]),
300 'progress_measure' => array('float', $row[10]),
301 'success_status' => array('text', $row[11]),
302 'scope' => array('text', $row[12])
303 ));
304 break;
305
306 case 'correct_response':
307 $cmi_interaction_id = null;
308 if ($row[1] !== null) {
309 for($i=0;$i<count($a_map_cmi_interaction_id);$i++)
310 if ($row[1] == $a_map_cmi_interaction_id[$i][0]) $cmi_interaction_id=$a_map_cmi_interaction_id[$i][1];
311 $row[0] = $ilDB->nextId('cmi_correct_response');
312 $ilDB->insert('cmi_correct_response', array(
313 'cmi_correct_resp_id' => array('integer', $row[0]),
314 'cmi_interaction_id' => array('integer', $cmi_interaction_id),
315 'pattern' => array('text', $row[2])
316 ));
317 }
318 break;
319 }
320 }
321 }
322 return $result;
323 }
324
325
326 // private function setGlobalObjectivesAndGetGlobalStatus($userId, $packageId, $data) {
327
328 // global $ilLog;
329 // $changed_seq_utilities=$data->changed_seq_utilities;
330 // $ilLog->write("SCORM2004 adl_seq_utilities changed: ".$changed_seq_utilities);
331 // if ($changed_seq_utilities == 1) {
332 // $returnAr=ilSCORM2004StoreData::writeGObjective($data->adl_seq_utilities, $userId, $packageId);
333 // }
334 // // $completed=$returnAr[0];
335 // // $satisfied=$returnAr[1];
336 // // $measure=$returnAr[2];
337 // self::ensureObjectDataCacheExistence();
338
339 // $lp_mode=$data->lp_mode;
340 // if ($lp_mode=="12") //12=scorm_package
341 // {
342 // include_once './Services/Tracking/classes/status/class.ilLPStatusSCORMPackage.php';
343 // $new_global_status=ilLPStatusSCORMPackage::determineStatus($packageId, $userId);
344 // }
345 // else $new_global_status = $data->now_global_status; //6=selected scos, 0=no tracking
346 // $ilLog->write("new_global_status=".$new_global_status);
347 // return $new_global_status;
348 // }
349
350
351 private function setGlobalObjectives($userId, $packageId, $data) {
352 global $ilLog;
353 $changed_seq_utilities=$data->changed_seq_utilities;
354 $ilLog->write("SCORM2004 adl_seq_utilities changed: ".$changed_seq_utilities);
355 if ($changed_seq_utilities == 1) {
356 $returnAr=ilSCORM2004StoreData::writeGObjective($data->adl_seq_utilities, $userId, $packageId);
357 }
358 }
359
360 public function syncGlobalStatus($userId, $packageId, $data, $new_global_status, $time_from_lms) {
361
362 global $ilDB, $ilLog;
363 $saved_global_status=$data->saved_global_status;
364 $ilLog->write("saved_global_status=".$saved_global_status);
365
366
367 //update percentage_completed, sco_total_time_sec,status in sahs_user
368 $totalTime=(int)$data->totalTimeCentisec;
369 $totalTime=round($totalTime/100);
370 $ilDB->queryF('UPDATE sahs_user SET sco_total_time_sec=%s, status=%s, percentage_completed=%s WHERE obj_id = %s AND user_id = %s',
371 array('integer', 'integer', 'integer', 'integer', 'integer'),
372 array($totalTime, $new_global_status, $data->percentageCompleted, $packageId, $userId));
373
374 self::ensureObjectDataCacheExistence();
375 global $ilObjDataCache;
376
377 // update learning progress
378 if ($new_global_status != null) {//could only happen when synchronising from SCORM Offline Player
379 include_once("./Services/Tracking/classes/class.ilObjUserTracking.php");
380 include_once("./Services/Tracking/classes/class.ilLPStatus.php");
381 ilLPStatus::writeStatus($packageId, $userId,$new_global_status,$data->percentageCompleted);
382
383// here put code for soap to MaxCMS e.g. when if($saved_global_status != $new_global_status)
384 }
385 // sync access number and time in read event table
386 if ($time_from_lms==false) {
387 include_once("./Modules/Scorm2004/classes/class.ilSCORM2004Tracking.php");
388 ilSCORM2004Tracking::_syncReadEvent($packageId, $userId, "sahs", (int)$_GET['ref_id'], $time_from_lms);
389 }
390 //end sync access number and time in read event table
391
392 return true;
393 }
394
395
396 //saves global_objectives to database
397 //$dowrite only if changed adl_seq_utilities
398 public function writeGObjective($g_data, $user, $package)
399 {
400 global $ilDB, $ilLog;
401 $ilLog->write("SCORM2004 writeGObjective");
402
403 $returnAr=array(null,null,null);
404
405 //iterate over assoziative array
406 if($g_data == null)
407 return $returnAr;
408
409 $rows_to_insert = Array();
410
411 foreach($g_data as $key => $value)
412 {
413 $ilLog->write("SCORM2004 writeGObjective -key: ".$key);
414 //objective
415 //learner = ilias learner id
416 //scope = null / course
417 foreach($value as $skey => $svalue)
418 {
419 $ilLog->write("SCORM2004 writeGObjective -skey: ".$skey);
420 //we always have objective and learner id
421 if($g_data->$key->$skey->$user->$package)
422 {
423 $o_value = $g_data->$key->$skey->$user->$package;
424 $scope = $package;
425 }
426 else //UK: is this okay? can $scope=0 and $user->{"null"}; when is $scope used?
427
428 {
429 //scope 0
430 $o_value = $g_data->$key->$skey->$user->{"null"};
431 //has to be converted to NULL in JS Later
432 $scope = 0;
433 }
434
435 //insert into database
436 $objective_id = $skey;
437 $toset = $o_value;
438 $dbuser = $user;
439
440 if($key == "status")
441 {
442
443 //special handling for status
444 $completed = $g_data->$key->$skey->$user->{completed};
445 $measure = $g_data->$key->$skey->$user->{measure};
446 $satisfied = $g_data->$key->$skey->$user->{satisfied};
447
448 $returnAr=array($completed, $satisfied, $measure);
449
450 $obj = '-course_overall_status-';
451 $pkg_id = $package;
452
453 $res = $ilDB->queryF('
454 SELECT user_id FROM cmi_gobjective
455 WHERE objective_id =%s
456 AND user_id = %s
457 AND scope_id = %s',
458 array('text', 'integer', 'integer'),
459 array($obj, $dbuser, $pkg_id)
460 );
461 $ilLog->write("SCORM2004 Count is: ".$ilDB->numRows($res));
462 if(!$ilDB->numRows($res))
463 {
464 $ilDB->manipulateF('
465 INSERT INTO cmi_gobjective
466 (user_id, status, scope_id, measure, satisfied, objective_id)
467 VALUES (%s, %s, %s, %s, %s, %s)',
468 array('integer', 'text', 'integer', 'text', 'text', 'text'),
469 array($dbuser, $completed, $pkg_id, $measure, $satisfied, $obj)
470 );
471 $ilLog->write("SCORM2004 cmi_gobjective Insert status=".$completed." scope_id=".$pkg_id." measure=".$measure." satisfied=".$satisfied." objective_id=".$obj);
472 }
473 else
474 {
475 $ilDB->manipulateF('
476 UPDATE cmi_gobjective
477 SET status = %s,
478 measure = %s,
479 satisfied = %s
480 WHERE objective_id = %s
481 AND user_id = %s
482 AND scope_id = %s',
483 array('text', 'text', 'text', 'text', 'integer', 'integer'),
484 array($completed, $measure, $satisfied, $obj, $dbuser, $pkg_id)
485 );
486 $ilLog->write("SCORM2004 cmi_gobjective Update status=".$completed." scope_id=".$pkg_id." measure=".$measure." satisfied=".$satisfied." objective_id=".$obj);
487 }
488 } else //add it to the rows_to_insert
489 {
490 //create the row if this is the first time it has been found
491 if($rows_to_insert[$objective_id] == NULL)
492 {
493 $rows_to_insert[$objective_id] = Array();
494 }
495 $rows_to_insert[$objective_id][$key] = $toset;
496 }
497
498 }
499 }
500
501 //Get the scope for all the global objectives!!!
502 $res = $ilDB->queryF("SELECT global_to_system
503 FROM cp_package
504 WHERE obj_id = %s",
505 array('text'),
506 array($package)
507 );
508
509 $scope_id = ($ilDB->fetchObject($res)->global_to_system) ? 0 : $package;
510
511 //build up the set to look for in the query
512 $existing_key_template = "";
513 foreach(array_keys($rows_to_insert) as $obj_id)
514 {
515 $existing_key_template .= "'{$obj_id}',";
516
517 }
518 //remove trailing ','
519 $existing_key_template = substr($existing_key_template, 0, strlen($existing_key_template) - 1);
520 $existing_keys = Array();
521
522 if($existing_key_template != "")
523 {
524 //Get the ones that need to be updated in a single query
525 $res = $ilDB->queryF("SELECT objective_id
526 FROM cmi_gobjective
527 WHERE user_id = %s
528 AND scope_id = %s
529 AND objective_id IN ($existing_key_template)",
530 array('integer', 'integer'),
531 array($dbuser, $scope_id)
532 );
533
534 while($row = $ilDB->fetchAssoc($res))
535 {
536 $existing_keys[] = $row['objective_id'];
537 }
538 }
539
540 foreach($rows_to_insert as $obj_id => $vals)
541 {
542 if(in_array($obj_id, $existing_keys))
543 {
544 $ilDB->manipulateF("UPDATE cmi_gobjective
545 SET satisfied=%s,
546 measure=%s,
547 score_raw=%s,
548 score_min=%s,
549 score_max=%s,
550 completion_status=%s,
551 progress_measure=%s
552 WHERE objective_id = %s
553 AND user_id = %s
554 AND scope_id = %s",
555
556 array('text','text', 'text', 'text', 'text', 'text',
557 'text', 'text', 'integer', 'integer'),
558
559 array($vals['satisfied'], $vals["measure"], $vals["score_raw"],
560 $vals["score_min"], $vals["score_max"],
561 $vals["completion_status"], $vals["progress_measure"],
562 $obj_id, $dbuser, $scope_id)
563 );
564 } else
565 {
566 $ilDB->manipulateF("INSERT INTO cmi_gobjective
567 (user_id, satisfied, measure, scope_id, status, objective_id,
568 score_raw, score_min, score_max, progress_measure, completion_status)
569 VALUES(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)",
570
571
572 array('integer', 'text', 'text', 'integer', 'text', 'text',
573 'text', 'text', 'text', 'text', 'text'),
574
575 array($dbuser, $vals['satisfied'], $vals['measure'],
576 $scope_id, NULL, $obj_id, $vals['score_raw'],
577 $vals['score_min'], $vals['score_max'],
578 $vals['progress_measure'], $vals['completion_status'])
579 );
580 }
581 }
582
583 // update learning progress here not necessary because integrated in setCMIdata
584 // check _updateStatus for cmi_gobjective
585// include_once("./Services/Tracking/classes/class.ilLPStatusWrapper.php");
586// ilLPStatusWrapper::_updateStatus($package, $user);
587
588 return $returnAr;
589 }
590
591 protected static function ensureObjectDataCacheExistence()
592 {
596 global $ilObjDataCache;
597
598 if($ilObjDataCache instanceof ilObjectDataCache)
599 {
600 return;
601 }
602
603 require_once './Services/Object/classes/class.ilObjectDataCache.php';
604 $ilObjDataCache = new ilObjectDataCache();
605 $GLOBALS['ilObjDataCache'] = $ilObjDataCache;
606 }
607
608
609
610}
$result
$_GET["client_id"]
static writeStatus($a_obj_id, $a_user_id, $a_status, $a_percentage=false, $a_force_per=false)
Write status for user and object.
class ilObjectDataCache
Class ilSCORM2004StoreData.
persistCMIData($userId=null, $packageId, $defaultLessonMode, $comments, $interactions, $objectives, $time_from_lms, $data=null)
setGlobalObjectives($userId, $packageId, $data)
scormPlayerUnload($userId=null, $packageId, $time_from_lms)
setCMIData($userId, $packageId, $data, $getComments, $getInteractions, $getObjectives)
checkIfAllowed($packageId, $userId, $hash)
writeGObjective($g_data, $user, $package)
syncGlobalStatus($userId, $packageId, $data, $new_global_status, $time_from_lms)
_syncReadEvent($a_obj_id, $a_user_id, $a_type, $a_ref_id, $time_from_lms=null)
Synch read event table.
$data
$GLOBALS['PHPCAS_CLIENT']
This global variable is used by the interface class phpCAS.
Definition: CAS.php:276
if(! $in) print
$packageId
global $ilDB
if((!isset($_SERVER['DOCUMENT_ROOT'])) OR(empty($_SERVER['DOCUMENT_ROOT']))) $_SERVER['DOCUMENT_ROOT']