MDL-16651 - add in delete attempt capability - thanks Dan/Tim.
[moodle.git] / mod / scorm / report.php
1 <?php  // $Id$
3 // This script uses installed report plugins to print quiz reports
5     require_once("../../config.php");
6     require_once('locallib.php');
8     $id = optional_param('id', '', PARAM_INT);    // Course Module ID, or
9     $a = optional_param('a', '', PARAM_INT);     // SCORM ID
10     $b = optional_param('b', '', PARAM_INT);     // SCO ID
11     $user = optional_param('user', '', PARAM_INT);  // User ID
12     $attempt = optional_param('attempt', '1', PARAM_INT);  // attempt number
13     $action     = optional_param('action', '', PARAM_ALPHA);
14     $attemptids = optional_param('attemptid', array(), PARAM_RAW); //get array of responses to delete.
16     if (!empty($id)) {
17         if (! $cm = get_coursemodule_from_id('scorm', $id)) {
18             print_error('invalidcoursemodule');
19         }
20         if (! $course = $DB->get_record('course', array('id'=>$cm->course))) {
21             print_error('coursemisconf');
22         }
23         if (! $scorm = $DB->get_record('scorm', array('id'=>$cm->instance))) {
24             print_error('invalidcoursemodule');
25         }
26     } else {
27         if (!empty($b)) {
28             if (! $sco = $DB->get_record('scorm_scoes', array('id'=>$b))) {
29                 print_error('invalidactivity', 'scorm');
30             }
31             $a = $sco->scorm;
32         }
33         if (!empty($a)) {
34             if (! $scorm = $DB->get_record('scorm', array('id'=>$a))) {
35                 print_error('invalidcoursemodule');
36             }
37             if (! $course = $DB->get_record('course', array('id'=>$scorm->course))) {
38                 print_error('coursemisconf');
39             }
40             if (! $cm = get_coursemodule_from_instance('scorm', $scorm->id, $course->id)) {
41                 print_error('invalidcoursemodule');
42             }
43         }
44     }
46     require_login($course->id, false, $cm);
48     $contextmodule = get_context_instance(CONTEXT_MODULE,$cm->id);
50     require_capability('mod/scorm:viewreport', $contextmodule);
52     add_to_log($course->id, 'scorm', 'report', 'report.php?id='.$cm->id, $scorm->id, $cm->id);
54     if (!empty($user)) {
55         $userdata = scorm_get_user_data($user);
56     } else {
57         $userdata = null;
58     }
60 /// Print the page header
61     if (empty($noheader)) {
63         $strscorms = get_string('modulenameplural', 'scorm');
64         $strscorm  = get_string('modulename', 'scorm');
65         $strreport  = get_string('report', 'scorm');
66         $strattempt  = get_string('attempt', 'scorm');
67         $strname  = get_string('name');
69         if (empty($b)) {
70             if (empty($a)) {
71                 $navigation = build_navigation('', $cm);
72                 print_header("$course->shortname: ".format_string($scorm->name), $course->fullname,$navigation,
73                              '', '', true);
74             } else {
76                 $navlinks = array();
77                 $navlinks[] = array('name' => $strreport, 'link' => "report.php?id=$cm->id", 'type' => 'title');
78                 $navlinks[] = array('name' => "$strattempt $attempt - ".fullname($userdata), 'link' => '', 'type' => 'title');
79                 $navigation = build_navigation($navlinks, $cm);
81                 print_header("$course->shortname: ".format_string($scorm->name), $course->fullname,
82                              $navigation, '', '', true);
83             }
84         } else {
86             $navlinks = array();
87             $navlinks[] = array('name' => $strreport, 'link' => "report.php?id=$cm->id", 'type' => 'title');
88             $navlinks[] = array('name' => "$strattempt $attempt - ".fullname($userdata), 'link' => "report.php?a=$a&amp;user=$user&amp;attempt=$attempt", 'type' => 'title');
89             $navlinks[] = array('name' => $sco->title, 'link' => '', 'type' => 'title');
90             $navigation = build_navigation($navlinks, $cm);
92             print_header("$course->shortname: ".format_string($scorm->name), $course->fullname, $navigation,
93                      '', '', true);
94         }
95         print_heading(format_string($scorm->name));
96     }
98     if ($action == 'delete' && has_capability('mod/scorm:deleteresponses',$contextmodule)) {
99         if (scorm_delete_responses($attemptids, $scorm->id)) { //delete responses.
100             notify(get_string('scormresponsedeleted', 'scorm'), 'notifysuccess');
101         }
102     }
104     $scormpixdir = $CFG->modpixpath.'/scorm/pix';
106     if (empty($b)) {
107         if (empty($a)) {
108             // No options, show the global scorm report
110             if (!empty($CFG->enablegroupings) && !empty($cm->groupingid)) {
111                 $sql = "SELECT st.userid, st.scormid
112                         FROM {scorm_scoes_track} st
113                             INNER JOIN {groups_members} gm ON st.userid = gm.userid
114                             INNER JOIN {groupings_groups} gg ON gm.groupid = gg.groupid
115                         WHERE st.scormid = ? AND gg.groupingid = ?
116                         GROUP BY st.userid,st.scormid
117                         ";
118                 $params = array($scorm->id, $cm->groupingid);
119             } else {
120                 $sql = "SELECT st.userid, st.scormid
121                         FROM {scorm_scoes_track} st
122                         WHERE st.scormid = ?
123                         GROUP BY st.userid,st.scormid
124                         ";
125                 $params = array($scorm->id);
126             }
128             if ($scousers=$DB->get_records_sql($sql, $params)) {
129                 $table = new stdClass();
130                 $table->head = array();
131                 $table->width = '100%';
132                 if (has_capability('mod/scorm:deleteresponses',$contextmodule)) {
133                     $table->head[]  = '&nbsp;';
134                     $table->align[] = 'center';
135                     $table->wrap[]  = 'nowrap';
136                     $table->size[]  = '10';
137                 }
139                 $table->head[]  = '&nbsp;';
140                 $table->align[] = 'center';
141                 $table->wrap[]  = 'nowrap';
142                 $table->size[]  = '10';
144                 $table->head[]  = get_string('name');
145                 $table->align[] = 'left';
146                 $table->wrap[]  = 'nowrap';
147                 $table->size[]  = '*';
149                 $table->head[]= get_string('attempt','scorm');
150                 $table->align[] = 'center';
151                 $table->wrap[] = 'nowrap';
152                 $table->size[] = '*';
154                 $table->head[]= get_string('started','scorm');
155                 $table->align[] = 'center';
156                 $table->wrap[] = 'nowrap';
157                 $table->size[] = '*';
159                 $table->head[]= get_string('last','scorm');
160                 $table->align[] = 'center';
161                 $table->wrap[] = 'nowrap';
162                 $table->size[] = '*';
164                 $table->head[]= get_string('score','scorm');
165                 $table->align[] = 'center';
166                 $table->wrap[] = 'nowrap';
167                 $table->size[] = '*';
169                 foreach($scousers as $scouser){
170                     $userdata = scorm_get_user_data($scouser->userid);
171                     $attempt = scorm_get_last_attempt($scorm->id,$scouser->userid);
172                     for ($a = 1; $a<=$attempt; $a++) {
173                         $row = array();
174                         if (has_capability('mod/scorm:deleteresponses',$contextmodule)) {
175                             $row[] = '<input type="checkbox" name="attemptid[]" value="'. $scouser->userid . ':' . $a . '" />';
176                         }
177                         $row[] = print_user_picture($scouser->userid, $course->id, $userdata->picture, false, true);
178                         $row[] = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$scouser->userid.'&amp;course='.$course->id.'">'.
179                                  fullname($userdata).'</a>';
180                         $row[] = '<a href="report.php?a='.$scorm->id.'&amp;user='.$scouser->userid.'&amp;attempt='.$a.'">'.$a.'</a>';
181                         $select = 'scormid = ? and userid = ? and attempt = ?';
182                         $params = array($scorm->id, $scouser->userid, $a);
183                         $timetracks = $DB->get_record_select('scorm_scoes_track', $select, $params, 'min(timemodified) as started, max(timemodified) as last');
184                         // jump out here if this attempt doesnt exist
185                         if (!$timetracks->started) {
186                             continue;
187                         }
188                         $row[] = userdate($timetracks->started, get_string('strftimedaydatetime'));
189                         $row[] = userdate($timetracks->last, get_string('strftimedaydatetime'));
191                         $row[] = scorm_grade_user_attempt($scorm, $scouser->userid, $a);
192                         $table->data[] = $row;
193                     }
194                 }
195                 echo '<div id="scormtablecontainer">';
196                 if (has_capability('mod/scorm:deleteresponses',$contextmodule)) {
197                     echo '<form id="attemptsform" method="post" action="'.$_SERVER['PHP_SELF'].'" onsubmit="var menu = document.getElementById(\'menuaction\'); return (menu.options[menu.selectedIndex].value == \'delete\' ? \''.addslashes(get_string('deleteattemptcheck','quiz')).'\' : true);">';
198                     echo '<input type="hidden" name="id" value="'.$id.'">';
199                     print_table($table);
200                     echo '<a href="javascript:select_all_in(\'DIV\',null,\'scormtablecontainer\');">'.get_string('selectall', 'quiz').'</a> / ';
201                     echo '<a href="javascript:deselect_all_in(\'DIV\',null,\'scormtablecontainer\');">'.get_string('selectnone', 'quiz').'</a> ';
202                     echo '&nbsp;&nbsp;';
203                     $options = array('delete' => get_string('delete'));
204                     echo choose_from_menu($options, 'action', '', get_string('withselected', 'quiz'), 'if(this.selectedIndex > 0) submitFormById(\'attemptsform\');', '', true);
205                     echo '<noscript id="noscriptmenuaction" style="display: inline;">';
206                     echo '<div>';
207                     echo '<input type="submit" value="'.get_string('go').'" /></div></noscript>';
208                     echo '<script type="text/javascript">'."\n<!--\n".'document.getElementById("noscriptmenuaction").style.display = "none";'."\n-->\n".'</script>';
209                     echo '</form>';
210                 } else {
211                     print_table($table);
212                 }
213                 echo '</div>';
214             } else {
215                 notify(get_string('noactivity', 'scorm'));
216             }
217         } else {
218             if (!empty($user)) {
219                 // User SCORM report
220                 if ($scoes = $DB->get_records_select('scorm_scoes',"scorm=? ORDER BY id", array($scorm->id))) {
221                     if (!empty($userdata)) {
222                         print_simple_box_start('center');
223                         echo '<div align="center">'."\n";
224                         print_user_picture($user, $course->id, $userdata->picture, false, false);
225                         echo "<a href=\"$CFG->wwwroot/user/view.php?id=$user&amp;course=$course->id\">".
226                              "$userdata->firstname $userdata->lastname</a><br />";
227                         echo get_string('attempt','scorm').': '.$attempt;
228                         echo '</div>'."\n";
229                         print_simple_box_end();
231                         // Print general score data
232                         $table = new stdClass();
233                         $table->head = array(get_string('title','scorm'),
234                                              get_string('status','scorm'),
235                                              get_string('time','scorm'),
236                                              get_string('score','scorm'),
237                                              '');
238                         $table->align = array('left', 'center','center','right','left');
239                         $table->wrap = array('nowrap', 'nowrap','nowrap','nowrap','nowrap');
240                         $table->width = '80%';
241                         $table->size = array('*', '*', '*', '*', '*');
242                         foreach ($scoes as $sco) {
243                             if ($sco->launch!='') {
244                                 $row = array();
245                                 $score = '&nbsp;';
246                                 if ($trackdata = scorm_get_tracks($sco->id,$user,$attempt)) {
247                                     if ($trackdata->score_raw != '') {
248                                         $score = $trackdata->score_raw;
249                                     }
250                                     if ($trackdata->status == '') {
251                                         $trackdata->status = 'notattempted';
252                                     }
253                                     $detailslink = '<a href="report.php?b='.$sco->id.'&amp;user='.$user.'&amp;attempt='.$attempt.'" title="'.
254                                                     get_string('details','scorm').'">'.get_string('details','scorm').'</a>';
255                                 } else {
256                                     $trackdata->status = 'notattempted';
257                                     $trackdata->total_time = '&nbsp;';
258                                     $detailslink = '&nbsp;';
259                                 }
260                                 $strstatus = get_string($trackdata->status,'scorm');
261                                 $row[] = '<img src="'.$scormpixdir.'/'.$trackdata->status.'.gif" alt="'.$strstatus.'" title="'.
262                                          $strstatus.'" />&nbsp;'.format_string($sco->title);
263                                 $row[] = get_string($trackdata->status,'scorm');
264                                 $row[] = $trackdata->total_time;
265                                 $row[] = $score;
266                                 $row[] = $detailslink;
267                             } else {
268                                 $row = array(format_string($sco->title), '&nbsp;', '&nbsp;', '&nbsp;', '&nbsp;');
269                             }
270                             $table->data[] = $row;
271                         }
272                         print_table($table);
273                     }
274                 }
275             } else {
276                 notice('No users to report');
277             }
278         }
279     } else {
280         // User SCO report
281         if (!empty($userdata)) {
282             print_simple_box_start('center');
283             //print_heading(format_string($sco->title));
284             print_heading('<a href="'.$CFG->wwwroot.'/mod/scorm/player.php?a='.$scorm->id.'&amp;mode=browse&amp;scoid='.$sco->id.'" target="_new">'.format_string($sco->title).'</a>');
285             echo '<div align="center">'."\n";
286             print_user_picture($user, $course->id, $userdata->picture, false, false);
287             echo "<a href=\"$CFG->wwwroot/user/view.php?id=$user&amp;course=$course->id\">".
288                  "$userdata->firstname $userdata->lastname</a><br />";
289             $scoreview = '';
290             if ($trackdata = scorm_get_tracks($sco->id,$user,$attempt)) {
291                 if ($trackdata->score_raw != '') {
292                     $scoreview = get_string('score','scorm').':&nbsp;'.$trackdata->score_raw;
293                 }
294                 if ($trackdata->status == '') {
295                     $trackdata->status = 'notattempted';
296                 }
297             } else {
298                 $trackdata->status = 'notattempted';
299                 $trackdata->total_time = '';
300             }
301             $strstatus = get_string($trackdata->status,'scorm');
302             echo '<img src="'.$scormpixdir.'/'.$trackdata->status.'.gif" alt="'.$strstatus.'" title="'.
303             $strstatus.'" />&nbsp;'.$trackdata->total_time.'<br />'.$scoreview.'<br />';
304             echo '</div>'."\n";
305             echo '<hr /><h2>'.get_string('details','scorm').'</h2>';
307             // Print general score data
308             $table = new stdClass();
309             $table->head = array(get_string('element','scorm'), get_string('value','scorm'));
310             $table->align = array('left', 'left');
311             $table->wrap = array('nowrap', 'nowrap');
312             $table->width = '100%';
313             $table->size = array('*', '*');
315             $existelements = false;
316             if ($scorm->version == 'SCORM_1.3') {
317                 $elements = array('raw' => 'cmi.score.raw',
318                                   'min' => 'cmi.score.min',
319                                   'max' => 'cmi.score.max',
320                                   'status' => 'cmi.completion_status',
321                                   'time' => 'cmi.total_time');
322             } else {
323                 $elements = array('raw' => 'cmi.core.score.raw',
324                                   'min' => 'cmi.core.score.min',
325                                   'max' => 'cmi.core.score.max',
326                                   'status' => 'cmi.core.lesson_status',
327                                   'time' => 'cmi.core.total_time');
328             }
329             $printedelements = array();
330             foreach ($elements as $key => $element) {
331                 if (isset($trackdata->$element)) {
332                     $existelements = true;
333                     $printedelements[]=$element;
334                     $row = array();
335                     $row[] = get_string($key,'scorm');
336                     $row[] = s($trackdata->$element);
337                     $table->data[] = $row;
338                 }
339             }
340             if ($existelements) {
341                 echo '<h3>'.get_string('general','scorm').'</h3>';
342                 print_table($table);
343             }
345             // Print Interactions data
346             $table = new stdClass();
347             $table->head = array(get_string('identifier','scorm'),
348                                  get_string('type','scorm'),
349                                  get_string('result','scorm'),
350                                  get_string('student_response','scorm'));
351             $table->align = array('center', 'center', 'center', 'center');
352             $table->wrap = array('nowrap', 'nowrap', 'nowrap', 'nowrap');
353             $table->width = '100%';
354             $table->size = array('*', '*', '*', '*', '*');
356             $existinteraction = false;
358             $i = 0;
359             $interactionid = 'cmi.interactions.'.$i.'.id';
361             while (isset($trackdata->$interactionid)) {
362                 $existinteraction = true;
363                 $printedelements[]=$interactionid;
364                 $elements = array($interactionid,
365                                   'cmi.interactions.'.$i.'.type',
366                                   'cmi.interactions.'.$i.'.result',
367                                   'cmi.interactions.'.$i.'.learner_response');
368                 $row = array();
369                 foreach ($elements as $element) {
370                     if (isset($trackdata->$element)) {
371                         $row[] = s($trackdata->$element);
372                         $printedelements[]=$element;
373                     } else {
374                         $row[] = '&nbsp;';
375                     }
376                 }
377                 $table->data[] = $row;
379                 $i++;
380                 $interactionid = 'cmi.interactions.'.$i.'.id';
381             }
382             if ($existinteraction) {
383                 echo '<h3>'.get_string('interactions','scorm').'</h3>';
384                 echo '<h3>'.get_string('interactions','scorm').'</h3>';
385                 print_table($table);
386             }
388             // Print Objectives data
389             $table = new stdClass();
390             $table->head = array(get_string('identifier','scorm'),
391                                  get_string('status','scorm'),
392                                  get_string('raw','scorm'),
393                                  get_string('min','scorm'),
394                                  get_string('max','scorm'));
395             $table->align = array('center', 'center', 'center', 'center', 'center');
396             $table->wrap = array('nowrap', 'nowrap', 'nowrap', 'nowrap', 'nowrap');
397             $table->width = '100%';
398             $table->size = array('*', '*', '*', '*', '*');
400             $existobjective = false;
402             $i = 0;
403             $objectiveid = 'cmi.objectives.'.$i.'.id';
405             while (isset($trackdata->$objectiveid)) {
406                 $existobjective = true;
407                 $printedelements[]=$objectiveid;
408                 $elements = array($objectiveid,
409                                   'cmi.objectives.'.$i.'.status',
410                                   'cmi.objectives.'.$i.'.score.raw',
411                                   'cmi.objectives.'.$i.'.score.min',
412                                   'cmi.objectives.'.$i.'.score.max');
413                 $row = array();
414                 foreach ($elements as $element) {
415                     if (isset($trackdata->$element)) {
416                         $row[] = s($trackdata->$element);
417                         $printedelements[]=$element;
418                     } else {
419                         $row[] = '&nbsp;';
420                     }
421                 }
422                 $table->data[] = $row;
424                 $i++;
425                 $objectiveid = 'cmi.objectives.'.$i.'.id';
426             }
427             if ($existobjective) {
428                 echo '<h3>'.get_string('objectives','scorm').'</h3>';
429                 print_table($table);
430             }
431             $table = new stdClass();
432             $table->head = array(get_string('element','scorm'), get_string('value','scorm'));
433             $table->align = array('left', 'left');
434             $table->wrap = array('nowrap', 'wrap');
435             $table->width = '100%';
436             $table->size = array('*', '*');
438             $existelements = false;
440             foreach($trackdata as $element => $value) {
441                 if (substr($element,0,3) == 'cmi') {
442                     if (!(in_array ($element, $printedelements))) {
443                         $existelements = true;
444                         $row = array();
445                         $row[] = get_string($element,'scorm') != '[['.$element.']]' ? get_string($element,'scorm') : $element;
446                         $row[] = s($value);
447                         $table->data[] = $row;
448                     }
449                 }
450             }
451             if ($existelements) {
452                 echo '<h3>'.get_string('othertracks','scorm').'</h3>';
453                 print_table($table);
454             }
455             print_simple_box_end();
456         } else {
457             print_error('missingparameter');
458         }
459     }
462     if (empty($noheader)) {
463         print_footer($course);
464     }
465 ?>