Merge branch 'm20_MDL-26176_cleanup' of github.com:danmarsden/moodle
[moodle.git] / mod / scorm / aicc.php
CommitLineData
32636f90 1<?php
4ecf8438 2 //Prevent Caching Headers
3 header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
4 header("Cache-Control: no-cache");
5 header("Pragma: no-cache");
6
03f5a0f8 7 require_once('../../config.php');
4d10b520
DM
8 include_once($CFG->dirroot.'/mod/scorm/lib.php');
9 require_once($CFG->dirroot.'/mod/scorm/locallib.php');
10 require_once($CFG->dirroot.'/mod/scorm/datamodels/aicclib.php');
4454447d
PS
11
12 foreach ($_POST as $key => $value) {
4d10b520
DM
13 $tempkey = strtolower($key);
14 $_POST[$tempkey] = $value;
4454447d 15 }
e5dd8e3b 16
03f5a0f8 17 $command = required_param('command', PARAM_ALPHA);
18 $sessionid = required_param('session_id', PARAM_ALPHANUM);
19 $aiccdata = optional_param('aicc_data', '', PARAM_RAW);
20
a6855934 21 $url = new moodle_url('/mod/scorm/aicc.php', array('command'=>$command,'session_id'=>$sessionid));
5c508e3f 22 if ($aiccdata !== 0) {
23 $url->param('aicc_data', $aiccdata);
24 }
25 $PAGE->set_url($url);
26
03f5a0f8 27 require_login();
4ecf8438 28
03f5a0f8 29 if (!empty($command) && confirm_sesskey($sessionid)) {
30 $command = strtolower($command);
4ecf8438 31
03f5a0f8 32 if (isset($SESSION->scorm_scoid)) {
33 $scoid = $SESSION->scorm_scoid;
34 } else {
1fe98e8d 35 print_error('cannotcallscript');
03f5a0f8 36 }
37 $mode = 'normal';
38 if (isset($SESSION->scorm_mode)) {
39 $mode = $SESSION->scorm_mode;
40 }
41 $status = 'Not Initialized';
42 if (isset($SESSION->scorm_status)) {
43 $status = $SESSION->scorm_status;
44 }
6006e06d
DM
45 if (isset($SESSION->scorm_attempt)) {
46 $attempt = $SESSION->scorm_attempt;
03f5a0f8 47 } else {
48 $attempt = 1;
49 }
50
b3659259 51 if ($sco = scorm_get_sco($scoid, SCO_ONLY)) {
c3f791c2 52 if (!$scorm = $DB->get_record('scorm',array('id'=>$sco->scorm))) {
1fe98e8d 53 print_error('cannotcallscript');
03f5a0f8 54 }
55 } else {
1fe98e8d 56 print_error('cannotcallscript');
03f5a0f8 57 }
a4c4962f
DM
58 $aiccrequest = "MOODLE scoid: $scoid"
59 . "\r\nMOODLE mode: $mode"
60 . "\r\nMOODLE status: $status"
61 . "\r\nMOODLE attempt: $attempt"
62 . "\r\nAICC sessionid: $sessionid"
63 . "\r\nAICC command: $command"
64 . "\r\nAICC aiccdata:\r\n$aiccdata";
65 scorm_debug_log_write("aicc", "HACP Request:\r\n$aiccrequest", $scoid);
169a204c 66 ob_start();
03f5a0f8 67
c3f791c2 68 if ($scorm = $DB->get_record('scorm',array('id'=>$sco->scorm))) {
03f5a0f8 69 switch ($command) {
70 case 'getparam':
71 if ($status == 'Not Initialized') {
72 $SESSION->scorm_status = 'Running';
73 $status = 'Running';
74 }
75 if ($status != 'Running') {
e341f9c1 76 echo "error=101\r\nerror_text=Terminated\r\n";
03f5a0f8 77 } else {
78 if ($usertrack=scorm_get_tracks($scoid,$USER->id,$attempt)) {
79 $userdata = $usertrack;
80 } else {
81 $userdata->status = '';
82 $userdata->score_raw = '';
83 }
84 $userdata->student_id = $USER->username;
85 $userdata->student_name = $USER->lastname .', '. $USER->firstname;
86 $userdata->mode = $mode;
87 if ($userdata->mode == 'normal') {
88 $userdata->credit = 'credit';
89 } else {
90 $userdata->credit = 'no-credit';
4ecf8438 91 }
92
b3659259 93 if ($sco = scorm_get_sco($scoid)) {
03f5a0f8 94 $userdata->course_id = $sco->identifier;
b3659259 95 $userdata->datafromlms = isset($sco->datafromlms)?$sco->datafromlms:'';
4ecf8438 96 $userdata->mastery_score = isset($sco->mastery_score)?$sco->mastery_score:'';
97 $userdata->max_time_allowed = isset($sco->max_time_allowed)?$sco->max_time_allowed:'';
98 $userdata->time_limit_action = isset($sco->time_limit_action)?$sco->time_limit_action:'';
99
e341f9c1 100 echo "error=0\r\nerror_text=Successful\r\naicc_data=";
101 echo "[Core]\r\n";
102 echo 'Student_ID='.$userdata->student_id."\r\n";
103 echo 'Student_Name='.$userdata->student_name."\r\n";
03f5a0f8 104 if (isset($userdata->{'cmi.core.lesson_location'})) {
e341f9c1 105 echo 'Lesson_Location='.$userdata->{'cmi.core.lesson_location'}."\r\n";
03f5a0f8 106 } else {
e341f9c1 107 echo 'Lesson_Location='."\r\n";
03f5a0f8 108 }
e341f9c1 109 echo 'Credit='.$userdata->credit."\r\n";
03f5a0f8 110 if (isset($userdata->status)) {
111 if ($userdata->status == '') {
112 $userdata->entry = ', ab-initio';
113 } else {
114 if (isset($userdata->{'cmi.core.exit'}) && ($userdata->{'cmi.core.exit'} == 'suspend')) {
115 $userdata->entry = ', resume';
116 } else {
117 $userdata->entry = '';
118 }
119 }
120 }
121 if (isset($userdata->{'cmi.core.lesson_status'})) {
e341f9c1 122 echo 'Lesson_Status='.$userdata->{'cmi.core.lesson_status'}.$userdata->entry."\r\n";
03f5a0f8 123 $SESSION->scorm_lessonstatus = $userdata->{'cmi.core.lesson_status'};
124 } else {
e341f9c1 125 echo 'Lesson_Status=not attempted'.$userdata->entry."\r\n";
03f5a0f8 126 $SESSION->scorm_lessonstatus = 'not attempted';
127 }
128 if (isset($userdata->{'cmi.core.score.raw'})) {
129 $max = '';
130 $min = '';
131 if (isset($userdata->{'cmi.core.score.max'}) && !empty($userdata->{'cmi.core.score.max'})) {
132 $max = ', '.$userdata->{'cmi.core.score.max'};
133 if (isset($userdata->{'cmi.core.score.min'}) && !empty($userdata->{'cmi.core.score.min'})) {
134 $min = ', '.$userdata->{'cmi.core.score.min'};
135 }
136 }
e341f9c1 137 echo 'Score='.$userdata->{'cmi.core.score.raw'}.$max.$min."\r\n";
03f5a0f8 138 } else {
e341f9c1 139 echo 'Score='."\r\n";
03f5a0f8 140 }
141 if (isset($userdata->{'cmi.core.total_time'})) {
e341f9c1 142 echo 'Time='.$userdata->{'cmi.core.total_time'}."\r\n";
03f5a0f8 143 } else {
e341f9c1 144 echo 'Time='.'00:00:00'."\r\n";
03f5a0f8 145 }
e341f9c1 146 echo 'Lesson_Mode='.$userdata->mode."\r\n";
03f5a0f8 147 if (isset($userdata->{'cmi.suspend_data'})) {
e341f9c1 148 echo "[Core_Lesson]\r\n".rawurldecode($userdata->{'cmi.suspend_data'})."\r\n";
03f5a0f8 149 } else {
e341f9c1 150 echo "[Core_Lesson]\r\n";
03f5a0f8 151 }
e341f9c1 152 echo "[Core_Vendor]\r\n".$userdata->datafromlms."\r\n";
153 echo "[Evaluation]\r\nCourse_ID = {".$userdata->course_id."}\r\n";
154 echo "[Student_Data]\r\n";
155 echo 'Mastery_Score='.$userdata->mastery_score."\r\n";
156 echo 'Max_Time_Allowed='.$userdata->max_time_allowed."\r\n";
157 echo 'Time_Limit_Action='.$userdata->time_limit_action."\r\n";
03f5a0f8 158 } else {
1fe98e8d 159 print_error('cannotfindsco', 'scorm');
03f5a0f8 160 }
161 }
162 break;
163 case 'putparam':
164 if ($status == 'Running') {
165 if (! $cm = get_coursemodule_from_instance("scorm", $scorm->id, $scorm->course)) {
e341f9c1 166 echo "error=1\r\nerror_text=Unknown\r\n"; // No one must see this error message if not hacked
03f5a0f8 167 }
168 if (!empty($aiccdata) && has_capability('mod/scorm:savetrack', get_context_instance(CONTEXT_MODULE, $cm->id))) {
169 $initlessonstatus = 'not attempted';
170 $lessonstatus = 'not attempted';
171 if (isset($SESSION->scorm_lessonstatus)) {
172 $initlessonstatus = $SESSION->scorm_lessonstatus;
173 }
174 $score = '';
175 $datamodel['lesson_location'] = 'cmi.core.lesson_location';
176 $datamodel['lesson_status'] = 'cmi.core.lesson_status';
177 $datamodel['score'] = 'cmi.core.score.raw';
178 $datamodel['time'] = 'cmi.core.session_time';
179 $datamodel['[core_lesson]'] = 'cmi.suspend_data';
180 $datamodel['[comments]'] = 'cmi.comments';
e341f9c1 181 $datarows = explode("\r\n",$aiccdata);
03f5a0f8 182 reset($datarows);
183 while ((list(,$datarow) = each($datarows)) !== false) {
184 if (($equal = strpos($datarow, '=')) !== false) {
185 $element = strtolower(trim(substr($datarow,0,$equal)));
186 $value = trim(substr($datarow,$equal+1));
187 if (isset($datamodel[$element])) {
188 $element = $datamodel[$element];
189 switch ($element) {
190 case 'cmi.core.lesson_location':
191 $id = scorm_insert_track($USER->id, $scorm->id, $sco->id, $attempt, $element, $value);
192 break;
193 case 'cmi.core.lesson_status':
194 $statuses = array(
195 'passed' => 'passed',
196 'completed' => 'completed',
197 'failed' => 'failed',
198 'incomplete' => 'incomplete',
199 'browsed' => 'browsed',
200 'not attempted' => 'not attempted',
201 'p' => 'passed',
202 'c' => 'completed',
203 'f' => 'failed',
204 'i' => 'incomplete',
205 'b' => 'browsed',
206 'n' => 'not attempted'
207 );
208 $exites = array(
209 'logout' => 'logout',
210 'time-out' => 'time-out',
211 'suspend' => 'suspend',
212 'l' => 'logout',
213 't' => 'time-out',
214 's' => 'suspend',
215 );
216 $values = explode(',',$value);
217 $value = '';
218 if (count($values) > 1) {
219 $value = trim(strtolower($values[1]));
e341f9c1 220 $value = $value[0];
03f5a0f8 221 if (isset($exites[$value])) {
222 $value = $exites[$value];
223 }
224 }
225 if (empty($value) || isset($exites[$value])) {
226 $subelement = 'cmi.core.exit';
227 $id = scorm_insert_track($USER->id, $scorm->id, $sco->id, $attempt, $subelement, $value);
228 }
229 $value = trim(strtolower($values[0]));
e341f9c1 230 $value = $value[0];
03f5a0f8 231 if (isset($statuses[$value]) && ($mode == 'normal')) {
232 $value = $statuses[$value];
233 $id = scorm_insert_track($USER->id, $scorm->id, $sco->id, $attempt, $element, $value);
234 }
235 $lessonstatus = $value;
236 break;
237 case 'cmi.core.score.raw':
238 $values = explode(',',$value);
239 if ((count($values) > 1) && ($values[1] >= $values[0]) && is_numeric($values[1])) {
240 $subelement = 'cmi.core.score.max';
241 $value = trim($values[1]);
242 $id = scorm_insert_track($USER->id, $scorm->id, $sco->id, $attempt, $subelement, $value);
243 if ((count($values) == 3) && ($values[2] <= $values[0]) && is_numeric($values[2])) {
244 $subelement = 'cmi.core.score.min';
245 $value = trim($values[2]);
246 $id = scorm_insert_track($USER->id, $scorm->id, $sco->id, $attempt, $subelement, $value);
247 }
248 }
4ecf8438 249
03f5a0f8 250 $value = '';
251 if (is_numeric($values[0])) {
e5dd8e3b 252 $value = trim($values[0]);
03f5a0f8 253 $id = scorm_insert_track($USER->id, $scorm->id, $sco->id, $attempt, $element, $value);
254 }
255 $score = $value;
256 break;
257 case 'cmi.core.session_time':
258 $SESSION->scorm_session_time = $value;
259 break;
260 }
261 }
262 } else {
263 if (isset($datamodel[strtolower(trim($datarow))])) {
264 $element = $datamodel[strtolower(trim($datarow))];
265 $value = '';
266 while ((($datarow = current($datarows)) !== false) && (substr($datarow,0,1) != '[')) {
e341f9c1 267 $value .= $datarow."\r\n";
03f5a0f8 268 next($datarows);
269 }
fd8a6a73 270 $value = rawurlencode(stripslashes($value)); // TODO: this is probably wrong, the stripslashes() has undefined meaning now; was this related to JS quoting or magic quotes?
03f5a0f8 271 $id = scorm_insert_track($USER->id, $scorm->id, $sco->id, $attempt, $element, $value);
272 }
4ecf8438 273 }
03f5a0f8 274 }
275 if (($mode == 'browse') && ($initlessonstatus == 'not attempted')){
276 $lessonstatus = 'browsed';
277 $id = scorm_insert_track($USER->id, $scorm->id, $sco->id, $attempt, 'cmi.core.lesson_status', 'browsed');
278 }
279 if ($mode == 'normal') {
58b57e28
DM
280 if ($sco = scorm_get_sco($scoid)) {
281 if (!empty($sco->mastery_score)) {
282 if (!empty($score)) {
283 if ($score >= $sco->mastery_score) {
284 $lessonstatus = 'passed';
285 } else {
286 $lessonstatus = 'failed';
0362f013 287 }
4ecf8438 288 }
03f5a0f8 289 }
58b57e28 290 $id = scorm_insert_track($USER->id, $scorm->id, $sco->id, $attempt, 'cmi.core.lesson_status', $lessonstatus);
03f5a0f8 291 }
4ecf8438 292 }
03f5a0f8 293 }
e341f9c1 294 echo "error=0\r\nerror_text=Successful\r\n";
03f5a0f8 295 } else if ($status == 'Terminated') {
e341f9c1 296 echo "error=1\r\nerror_text=Terminated\r\n";
03f5a0f8 297 } else {
e341f9c1 298 echo "error=1\r\nerror_text=Not Initialized\r\n";
03f5a0f8 299 }
300 break;
301 case 'putcomments':
302 if ($status == 'Running') {
e341f9c1 303 echo "error=0\r\nerror_text=Successful\r\n";
03f5a0f8 304 } else if ($status == 'Terminated') {
e341f9c1 305 echo "error=1\r\nerror_text=Terminated\r\n";
03f5a0f8 306 } else {
e341f9c1 307 echo "error=1\r\nerror_text=Not Initialized\r\n";
03f5a0f8 308 }
309 break;
310 case 'putinteractions':
311 if ($status == 'Running') {
e341f9c1 312 echo "error=0\r\nerror_text=Successful\r\n";
03f5a0f8 313 } else if ($status == 'Terminated') {
e341f9c1 314 echo "error=1\r\nerror_text=Terminated\r\n";
03f5a0f8 315 } else {
e341f9c1 316 echo "error=1\r\nerror_text=Not Initialized\r\n";
03f5a0f8 317 }
318 break;
319 case 'putobjectives':
320 if ($status == 'Running') {
e341f9c1 321 echo "error=0\r\nerror_text=Successful\r\n";
03f5a0f8 322 } else if ($status == 'Terminated') {
e341f9c1 323 echo "error=1\r\nerror_text=Terminated\r\n";
03f5a0f8 324 } else {
e341f9c1 325 echo "error=1\r\nerror_text=Not Initialized\r\n";
03f5a0f8 326 }
327 break;
328 case 'putpath':
329 if ($status == 'Running') {
e341f9c1 330 echo "error=0\r\nerror_text=Successful\r\n";
03f5a0f8 331 } else if ($status == 'Terminated') {
e341f9c1 332 echo "error=1\r\nerror_text=Terminated\r\n";
03f5a0f8 333 } else {
e341f9c1 334 echo "error=1\r\nerror_text=Not Initialized\r\n";
03f5a0f8 335 }
336 break;
337 case 'putperformance':
338 if ($status == 'Running') {
e341f9c1 339 echo "error=0\r\nerror_text=Successful\r\n";
03f5a0f8 340 } else if ($status == 'Terminated') {
e341f9c1 341 echo "error=1\r\nerror_text=Terminated\r\n";
03f5a0f8 342 } else {
e341f9c1 343 echo "error=1\r\nerror_text=Not Initialized\r\n";
03f5a0f8 344 }
345 break;
346 case 'exitau':
347 if ($status == 'Running') {
348 if (isset($SESSION->scorm_session_time) && ($SESSION->scorm_session_time != '')) {
3b569743 349 if ($track = $DB->get_record('scorm_scoes_track',array("userid"=>$USER->id, "scormid"=>$scorm->id,"scoid"=>$sco->id, "attempt"=>$attempt,"element"=>'cmi.core.total_time'))) {
4ecf8438 350 // Add session_time to total_time
03f5a0f8 351 $value = scorm_add_time($track->value, $SESSION->scorm_session_time);
352 $track->value = $value;
353 $track->timemodified = time();
dd88de0e 354 $DB->update_record('scorm_scoes_track',$track);
03f5a0f8 355 } else {
39790bd8 356 $track = new stdClass();
03f5a0f8 357 $track->userid = $USER->id;
358 $track->scormid = $scorm->id;
359 $track->scoid = $sco->id;
360 $track->element = 'cmi.core.total_time';
361 $track->value = $SESSION->scorm_session_time;
3b569743 362 $track->attempt = $attempt;
03f5a0f8 363 $track->timemodified = time();
c6089d93 364 $id = $DB->insert_record('scorm_scoes_track',$track);
03f5a0f8 365 }
074b6db2 366 scorm_update_grades($scorm, $USER->id);
03f5a0f8 367 }
03f5a0f8 368 $SESSION->scorm_status = 'Terminated';
369 $SESSION->scorm_session_time = '';
e341f9c1 370 echo "error=0\r\nerror_text=Successful\r\n";
03f5a0f8 371 } else if ($status == 'Terminated') {
e341f9c1 372 echo "error=1\r\nerror_text=Terminated\r\n";
03f5a0f8 373 } else {
e341f9c1 374 echo "error=1\r\nerror_text=Not Initialized\r\n";
03f5a0f8 375 }
376 break;
377 default:
e341f9c1 378 echo "error=1\r\nerror_text=Invalid Command\r\n";
03f5a0f8 379 break;
380 }
381 }
382 } else {
383 if (empty($command)) {
e341f9c1 384 echo "error=1\r\nerror_text=Invalid Command\r\n";
03f5a0f8 385 } else {
e341f9c1 386 echo "error=3\r\nerror_text=Invalid Session ID\r\n";
03f5a0f8 387 }
388 }
169a204c 389 $aiccresponse = ob_get_contents();
a4c4962f 390 scorm_debug_log_write("aicc", "HACP Response:\r\n$aiccresponse", $scoid);
169a204c 391 ob_end_flush();