|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 // This file is part of Moodle - http://moodle.org/ 00003 // 00004 // Moodle is free software: you can redistribute it and/or modify 00005 // it under the terms of the GNU General Public License as published by 00006 // the Free Software Foundation, either version 3 of the License, or 00007 // (at your option) any later version. 00008 // 00009 // Moodle is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU General Public License 00015 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 00024 defined('MOODLE_INTERNAL') || die(); 00025 00026 class scorm_basic_report extends scorm_default_report { 00034 function display($scorm, $cm, $course, $download) { 00035 global $CFG, $DB, $OUTPUT, $PAGE; 00036 $contextmodule= get_context_instance(CONTEXT_MODULE, $cm->id); 00037 $action = optional_param('action', '', PARAM_ALPHA); 00038 $attemptids = optional_param_array('attemptid', array(), PARAM_RAW); 00039 $attemptsmode = optional_param('attemptsmode', SCORM_REPORT_ATTEMPTS_ALL_STUDENTS, PARAM_INT); 00040 $PAGE->set_url(new moodle_url($PAGE->url, array('attemptsmode' => $attemptsmode))); 00041 00042 if ($action == 'delete' && has_capability('mod/scorm:deleteresponses', $contextmodule) && confirm_sesskey()) { 00043 if (scorm_delete_responses($attemptids, $scorm)) { //delete responses. 00044 add_to_log($course->id, 'scorm', 'delete attempts', 'report.php?id=' . $cm->id, implode(",", $attemptids), $cm->id); 00045 echo $OUTPUT->notification(get_string('scormresponsedeleted', 'scorm'), 'notifysuccess'); 00046 } 00047 } 00048 // find out current groups mode 00049 $currentgroup = groups_get_activity_group($cm, true); 00050 00051 // detailed report 00052 $mform = new mod_scorm_report_settings($PAGE->url, compact('currentgroup')); 00053 if ($fromform = $mform->get_data()) { 00054 $detailedrep = $fromform->detailedrep; 00055 $pagesize = $fromform->pagesize; 00056 set_user_preference('scorm_report_detailed', $detailedrep); 00057 set_user_preference('scorm_report_pagesize', $pagesize); 00058 } else { 00059 $detailedrep = get_user_preferences('scorm_report_detailed', false); 00060 $pagesize = get_user_preferences('scorm_report_pagesize', 0); 00061 } 00062 if ($pagesize < 1) { 00063 $pagesize = SCORM_REPORT_DEFAULT_PAGE_SIZE; 00064 } 00065 00066 // select group menu 00067 $displayoptions = array(); 00068 $displayoptions['attemptsmode'] = $attemptsmode; 00069 if ($groupmode = groups_get_activity_groupmode($cm)) { // Groups are being used 00070 if (!$download) { 00071 groups_print_activity_menu($cm, new moodle_url($PAGE->url, $displayoptions)); 00072 } 00073 } 00074 00075 // We only want to show the checkbox to delete attempts 00076 // if the user has permissions and if the report mode is showing attempts. 00077 $candelete = has_capability('mod/scorm:deleteresponses', $contextmodule) 00078 && ($attemptsmode!= SCORM_REPORT_ATTEMPTS_STUDENTS_WITH_NO); 00079 // select the students 00080 $nostudents = false; 00081 00082 if (empty($currentgroup)) { 00083 // all users who can attempt scoes 00084 if (!$students = get_users_by_capability($contextmodule, 'mod/scorm:savetrack', '', '', '', '', '', '', false)) { 00085 echo $OUTPUT->notification(get_string('nostudentsyet')); 00086 $nostudents = true; 00087 $allowedlist = ''; 00088 } else { 00089 $allowedlist = array_keys($students); 00090 } 00091 } else { 00092 // all users who can attempt scoes and who are in the currently selected group 00093 if (!$groupstudents = get_users_by_capability($contextmodule, 'mod/scorm:savetrack', '', '', '', '', $currentgroup, '', false)) { 00094 echo $OUTPUT->notification(get_string('nostudentsingroup')); 00095 $nostudents = true; 00096 $groupstudents = array(); 00097 } 00098 $allowedlist = array_keys($groupstudents); 00099 } 00100 00101 if ( !$nostudents ) { 00102 // Now check if asked download of data 00103 $coursecontext = context_course::instance($course->id); 00104 if ($download) { 00105 $shortname = format_string($course->shortname, true, array('context' => $coursecontext)); 00106 $filename = clean_filename("$shortname ".format_string($scorm->name, true)); 00107 } 00108 00109 // Define table columns 00110 $columns = array(); 00111 $headers = array(); 00112 if (!$download && $candelete) { 00113 $columns[]= 'checkbox'; 00114 $headers[]= null; 00115 } 00116 if (!$download && $CFG->grade_report_showuserimage) { 00117 $columns[]= 'picture'; 00118 $headers[]= ''; 00119 } 00120 $columns[]= 'fullname'; 00121 $headers[]= get_string('name'); 00122 $extrafields = get_extra_user_fields($coursecontext); 00123 foreach ($extrafields as $field) { 00124 $columns[] = $field; 00125 $headers[] = get_user_field_name($field); 00126 } 00127 00128 $columns[]= 'attempt'; 00129 $headers[]= get_string('attempt', 'scorm'); 00130 $columns[]= 'start'; 00131 $headers[]= get_string('started', 'scorm'); 00132 $columns[]= 'finish'; 00133 $headers[]= get_string('last', 'scorm'); 00134 $columns[]= 'score'; 00135 $headers[]= get_string('score', 'scorm'); 00136 if ($detailedrep && $scoes = $DB->get_records('scorm_scoes', array("scorm"=>$scorm->id), 'id')) { 00137 foreach ($scoes as $sco) { 00138 if ($sco->launch!='') { 00139 $columns[]= 'scograde'.$sco->id; 00140 $headers[]= format_string($sco->title); 00141 } 00142 } 00143 } else { 00144 $scoes = null; 00145 } 00146 00147 if (!$download) { 00148 $table = new flexible_table('mod-scorm-report'); 00149 00150 $table->define_columns($columns); 00151 $table->define_headers($headers); 00152 $table->define_baseurl($PAGE->url); 00153 00154 $table->sortable(true); 00155 $table->collapsible(true); 00156 00157 // This is done to prevent redundant data, when a user has multiple attempts 00158 $table->column_suppress('picture'); 00159 $table->column_suppress('fullname'); 00160 foreach ($extrafields as $field) { 00161 $table->column_suppress($field); 00162 } 00163 00164 $table->no_sorting('start'); 00165 $table->no_sorting('finish'); 00166 $table->no_sorting('score'); 00167 if ( $scoes ) { 00168 foreach ($scoes as $sco) { 00169 if ($sco->launch!='') { 00170 $table->no_sorting('scograde'.$sco->id); 00171 } 00172 } 00173 } 00174 00175 $table->column_class('picture', 'picture'); 00176 $table->column_class('fullname', 'bold'); 00177 $table->column_class('score', 'bold'); 00178 00179 $table->set_attribute('cellspacing', '0'); 00180 $table->set_attribute('id', 'attempts'); 00181 $table->set_attribute('class', 'generaltable generalbox'); 00182 00183 // Start working -- this is necessary as soon as the niceties are over 00184 $table->setup(); 00185 } else if ($download =='ODS') { 00186 require_once("$CFG->libdir/odslib.class.php"); 00187 00188 $filename .= ".ods"; 00189 // Creating a workbook 00190 $workbook = new MoodleODSWorkbook("-"); 00191 // Sending HTTP headers 00192 $workbook->send($filename); 00193 // Creating the first worksheet 00194 $sheettitle = get_string('report', 'scorm'); 00195 $myxls =& $workbook->add_worksheet($sheettitle); 00196 // format types 00197 $format =& $workbook->add_format(); 00198 $format->set_bold(0); 00199 $formatbc =& $workbook->add_format(); 00200 $formatbc->set_bold(1); 00201 $formatbc->set_align('center'); 00202 $formatb =& $workbook->add_format(); 00203 $formatb->set_bold(1); 00204 $formaty =& $workbook->add_format(); 00205 $formaty->set_bg_color('yellow'); 00206 $formatc =& $workbook->add_format(); 00207 $formatc->set_align('center'); 00208 $formatr =& $workbook->add_format(); 00209 $formatr->set_bold(1); 00210 $formatr->set_color('red'); 00211 $formatr->set_align('center'); 00212 $formatg =& $workbook->add_format(); 00213 $formatg->set_bold(1); 00214 $formatg->set_color('green'); 00215 $formatg->set_align('center'); 00216 // Here starts workshhet headers 00217 00218 $colnum = 0; 00219 foreach ($headers as $item) { 00220 $myxls->write(0, $colnum, $item, $formatbc); 00221 $colnum++; 00222 } 00223 $rownum=1; 00224 } else if ($download =='Excel') { 00225 require_once("$CFG->libdir/excellib.class.php"); 00226 00227 $filename .= ".xls"; 00228 // Creating a workbook 00229 $workbook = new MoodleExcelWorkbook("-"); 00230 // Sending HTTP headers 00231 $workbook->send($filename); 00232 // Creating the first worksheet 00233 $sheettitle = get_string('report', 'scorm'); 00234 $myxls =& $workbook->add_worksheet($sheettitle); 00235 // format types 00236 $format =& $workbook->add_format(); 00237 $format->set_bold(0); 00238 $formatbc =& $workbook->add_format(); 00239 $formatbc->set_bold(1); 00240 $formatbc->set_align('center'); 00241 $formatb =& $workbook->add_format(); 00242 $formatb->set_bold(1); 00243 $formaty =& $workbook->add_format(); 00244 $formaty->set_bg_color('yellow'); 00245 $formatc =& $workbook->add_format(); 00246 $formatc->set_align('center'); 00247 $formatr =& $workbook->add_format(); 00248 $formatr->set_bold(1); 00249 $formatr->set_color('red'); 00250 $formatr->set_align('center'); 00251 $formatg =& $workbook->add_format(); 00252 $formatg->set_bold(1); 00253 $formatg->set_color('green'); 00254 $formatg->set_align('center'); 00255 00256 $colnum = 0; 00257 foreach ($headers as $item) { 00258 $myxls->write(0, $colnum, $item, $formatbc); 00259 $colnum++; 00260 } 00261 $rownum=1; 00262 } else if ($download=='CSV') { 00263 $filename .= ".txt"; 00264 header("Content-Type: application/download\n"); 00265 header("Content-Disposition: attachment; filename=\"$filename\""); 00266 header("Expires: 0"); 00267 header("Cache-Control: must-revalidate,post-check=0,pre-check=0"); 00268 header("Pragma: public"); 00269 echo implode("\t", $headers)." \n"; 00270 } 00271 $params = array(); 00272 list($usql, $params) = $DB->get_in_or_equal($allowedlist, SQL_PARAMS_NAMED); 00273 // Construct the SQL 00274 $select = 'SELECT DISTINCT '.$DB->sql_concat('u.id', '\'#\'', 'COALESCE(st.attempt, 0)').' AS uniqueid, '; 00275 $select .= 'st.scormid AS scormid, st.attempt AS attempt, ' . 00276 'u.id AS userid, u.idnumber, u.firstname, u.lastname, u.picture, u.imagealt, u.email' . 00277 get_extra_user_fields_sql($coursecontext, 'u', '', array('idnumber')) . ' '; 00278 00279 // This part is the same for all cases - join users and scorm_scoes_track tables 00280 $from = 'FROM {user} u '; 00281 $from .= 'LEFT JOIN {scorm_scoes_track} st ON st.userid = u.id AND st.scormid = '.$scorm->id; 00282 switch ($attemptsmode) { 00283 case SCORM_REPORT_ATTEMPTS_STUDENTS_WITH: 00284 // Show only students with attempts 00285 $where = ' WHERE u.id ' .$usql. ' AND st.userid IS NOT NULL'; 00286 break; 00287 case SCORM_REPORT_ATTEMPTS_STUDENTS_WITH_NO: 00288 // Show only students without attempts 00289 $where = ' WHERE u.id ' .$usql. ' AND st.userid IS NULL'; 00290 break; 00291 case SCORM_REPORT_ATTEMPTS_ALL_STUDENTS: 00292 // Show all students with or without attempts 00293 $where = ' WHERE u.id ' .$usql. ' AND (st.userid IS NOT NULL OR st.userid IS NULL)'; 00294 break; 00295 } 00296 00297 $countsql = 'SELECT COUNT(DISTINCT('.$DB->sql_concat('u.id', '\'#\'', 'COALESCE(st.attempt, 0)').')) AS nbresults, '; 00298 $countsql .= 'COUNT(DISTINCT('.$DB->sql_concat('u.id', '\'#\'', 'st.attempt').')) AS nbattempts, '; 00299 $countsql .= 'COUNT(DISTINCT(u.id)) AS nbusers '; 00300 $countsql .= $from.$where; 00301 00302 if (!$download) { 00303 $sort = $table->get_sql_sort(); 00304 } else { 00305 $sort = ''; 00306 } 00307 // Fix some wired sorting 00308 if (empty($sort)) { 00309 $sort = ' ORDER BY uniqueid'; 00310 } else { 00311 $sort = ' ORDER BY '.$sort; 00312 } 00313 00314 if (!$download) { 00315 // Add extra limits due to initials bar 00316 list($twhere, $tparams) = $table->get_sql_where(); 00317 if ($twhere) { 00318 $where .= ' AND '.$twhere; //initial bar 00319 $params = array_merge($params, $tparams); 00320 } 00321 00322 if (!empty($countsql)) { 00323 $count = $DB->get_record_sql($countsql, $params); 00324 $totalinitials = $count->nbresults; 00325 if ($twhere) { 00326 $countsql .= ' AND '.$twhere; 00327 } 00328 $count = $DB->get_record_sql($countsql, $params); 00329 $total = $count->nbresults; 00330 } 00331 00332 $table->pagesize($pagesize, $total); 00333 00334 echo '<div class="quizattemptcounts">'; 00335 if ( $count->nbresults == $count->nbattempts ) { 00336 echo get_string('reportcountattempts', 'scorm', $count); 00337 } else if ( $count->nbattempts>0 ) { 00338 echo get_string('reportcountallattempts', 'scorm', $count); 00339 } else { 00340 echo $count->nbusers.' '.get_string('users'); 00341 } 00342 echo '</div>'; 00343 } 00344 00345 // Fetch the attempts 00346 if (!$download) { 00347 $attempts = $DB->get_records_sql($select.$from.$where.$sort, $params, 00348 $table->get_page_start(), $table->get_page_size()); 00349 echo '<div id="scormtablecontainer">'; 00350 if ($candelete) { 00351 // Start form 00352 $strreallydel = addslashes_js(get_string('deleteattemptcheck', 'scorm')); 00353 echo '<form id="attemptsform" method="post" action="' . $PAGE->url->out(false) . 00354 '" onsubmit="return confirm(\''.$strreallydel.'\');">'; 00355 echo '<input type="hidden" name="action" value="delete"/>'; 00356 echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />'; 00357 echo '<div style="display: none;">'; 00358 echo html_writer::input_hidden_params($PAGE->url); 00359 echo '</div>'; 00360 echo '<div>'; 00361 } 00362 $table->initialbars($totalinitials>20); // Build table rows 00363 } else { 00364 $attempts = $DB->get_records_sql($select.$from.$where.$sort, $params); 00365 } 00366 00367 if ($attempts) { 00368 foreach ($attempts as $scouser) { 00369 $row = array(); 00370 if (!empty($scouser->attempt)) { 00371 $timetracks = scorm_get_sco_runtime($scorm->id, false, $scouser->userid, $scouser->attempt); 00372 } else { 00373 $timetracks = ''; 00374 } 00375 if (in_array('checkbox', $columns)) { 00376 if ($candelete && !empty($timetracks->start)) { 00377 $row[] = '<input type="checkbox" name="attemptid[]" value="'. $scouser->userid . ':' . $scouser->attempt . '" />'; 00378 } else if ($candelete) { 00379 $row[] = ''; 00380 } 00381 } 00382 if (in_array('picture', $columns)) { 00383 $user = (object)array( 00384 'id'=>$scouser->userid, 00385 'picture'=>$scouser->picture, 00386 'imagealt'=>$scouser->imagealt, 00387 'email'=>$scouser->email, 00388 'firstname'=>$scouser->firstname, 00389 'lastname'=>$scouser->lastname); 00390 $row[] = $OUTPUT->user_picture($user, array('courseid'=>$course->id)); 00391 } 00392 if (!$download) { 00393 $row[] = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$scouser->userid.'&course='.$course->id.'">'.fullname($scouser).'</a>'; 00394 } else { 00395 $row[] = fullname($scouser); 00396 } 00397 foreach ($extrafields as $field) { 00398 $row[] = s($scouser->{$field}); 00399 } 00400 if (empty($timetracks->start)) { 00401 $row[] = '-'; 00402 $row[] = '-'; 00403 $row[] = '-'; 00404 $row[] = '-'; 00405 } else { 00406 if (!$download) { 00407 $row[] = '<a href="userreport.php?a='.$scorm->id.'&user='.$scouser->userid.'&attempt='.$scouser->attempt.'">'.$scouser->attempt.'</a>'; 00408 } else { 00409 $row[] = $scouser->attempt; 00410 } 00411 if ($download =='ODS' || $download =='Excel' ) { 00412 $row[] = userdate($timetracks->start, get_string("strftimedatetime", "langconfig")); 00413 } else { 00414 $row[] = userdate($timetracks->start); 00415 } 00416 if ($download =='ODS' || $download =='Excel' ) { 00417 $row[] = userdate($timetracks->finish, get_string('strftimedatetime', 'langconfig')); 00418 } else { 00419 $row[] = userdate($timetracks->finish); 00420 } 00421 $row[] = scorm_grade_user_attempt($scorm, $scouser->userid, $scouser->attempt); 00422 } 00423 // print out all scores of attempt 00424 if ($scoes) { 00425 foreach ($scoes as $sco) { 00426 if ($sco->launch!='') { 00427 if ($trackdata = scorm_get_tracks($sco->id, $scouser->userid, $scouser->attempt)) { 00428 if ($trackdata->status == '') { 00429 $trackdata->status = 'notattempted'; 00430 } 00431 $strstatus = get_string($trackdata->status, 'scorm'); 00432 // if raw score exists, print it 00433 if ($trackdata->score_raw != '') { 00434 $score = $trackdata->score_raw; 00435 // add max score if it exists 00436 if (scorm_version_check($scorm->version, SCORM_13)) { 00437 $maxkey = 'cmi.score.max'; 00438 } else { 00439 $maxkey = 'cmi.core.score.max'; 00440 } 00441 if (isset($trackdata->$maxkey)) { 00442 $score .= '/'.$trackdata->$maxkey; 00443 } 00444 // else print out status 00445 } else { 00446 $score = $strstatus; 00447 } 00448 if (!$download) { 00449 $row[] = '<img src="'.$OUTPUT->pix_url($trackdata->status, 'scorm').'" alt="'.$strstatus.'" title="'.$strstatus.'" /><br/> 00450 <a href="userreport.php?b='.$sco->id.'&user='.$scouser->userid.'&attempt='.$scouser->attempt. 00451 '" title="'.get_string('details', 'scorm').'">'.$score.'</a>'; 00452 } else { 00453 $row[] = $score; 00454 } 00455 } else { 00456 // if we don't have track data, we haven't attempted yet 00457 $strstatus = get_string('notattempted', 'scorm'); 00458 if (!$download) { 00459 $row[] = '<img src="'.$OUTPUT->pix_url('notattempted', 'scorm').'" alt="'.$strstatus.'" title="'.$strstatus.'" /><br/>'.$strstatus; 00460 } else { 00461 $row[] = $strstatus; 00462 } 00463 } 00464 } 00465 } 00466 } 00467 00468 if (!$download) { 00469 $table->add_data($row); 00470 } else if ($download == 'Excel' or $download == 'ODS') { 00471 $colnum = 0; 00472 foreach ($row as $item) { 00473 $myxls->write($rownum, $colnum, $item, $format); 00474 $colnum++; 00475 } 00476 $rownum++; 00477 } else if ($download=='CSV') { 00478 $text = implode("\t", $row); 00479 echo $text." \n"; 00480 } 00481 } 00482 if (!$download) { 00483 $table->finish_output(); 00484 if ($candelete) { 00485 echo '<table id="commands">'; 00486 echo '<tr><td>'; 00487 echo '<a href="javascript:select_all_in(\'DIV\', null, \'scormtablecontainer\');">'. 00488 get_string('selectall', 'scorm').'</a> / '; 00489 echo '<a href="javascript:deselect_all_in(\'DIV\', null, \'scormtablecontainer\');">'. 00490 get_string('selectnone', 'scorm').'</a> '; 00491 echo ' '; 00492 echo '<input type="submit" value="'.get_string('deleteselected', 'quiz_overview').'"/>'; 00493 echo '</td></tr></table>'; 00494 // Close form 00495 echo '</div>'; 00496 echo '</form>'; 00497 } 00498 echo '</div>'; 00499 if (!empty($attempts)) { 00500 echo '<table class="boxaligncenter"><tr>'; 00501 echo '<td>'; 00502 echo $OUTPUT->single_button(new moodle_url($PAGE->url, 00503 array('download'=>'ODS') + $displayoptions), 00504 get_string('downloadods')); 00505 echo "</td>\n"; 00506 echo '<td>'; 00507 echo $OUTPUT->single_button(new moodle_url($PAGE->url, 00508 array('download'=>'Excel') + $displayoptions), 00509 get_string('downloadexcel')); 00510 echo "</td>\n"; 00511 echo '<td>'; 00512 echo $OUTPUT->single_button(new moodle_url($PAGE->url, 00513 array('download'=>'CSV') + $displayoptions), 00514 get_string('downloadtext')); 00515 echo "</td>\n"; 00516 echo "<td>"; 00517 echo "</td>\n"; 00518 echo '</tr></table>'; 00519 } 00520 } 00521 } else { 00522 if ($candelete && !$download) { 00523 echo '</div>'; 00524 echo '</form>'; 00525 $table->finish_output(); 00526 } 00527 echo '</div>'; 00528 } 00529 // Show preferences form irrespective of attempts are there to report or not 00530 if (!$download) { 00531 $mform->set_data(compact('detailedrep', 'pagesize', 'attemptsmode')); 00532 $mform->display(); 00533 } 00534 if ($download == 'Excel' or $download == 'ODS') { 00535 $workbook->close(); 00536 exit; 00537 } else if ($download == 'CSV') { 00538 exit; 00539 } 00540 } else { 00541 echo $OUTPUT->notification(get_string('noactivity', 'scorm')); 00542 } 00543 }// function ends 00544 }