|
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/>. 00016 00027 defined('MOODLE_INTERNAL') || die(); 00028 00029 require_once($CFG->dirroot . '/mod/quiz/lib.php'); 00030 require_once($CFG->libdir . '/filelib.php'); 00031 00032 define('QUIZ_REPORT_DEFAULT_PAGE_SIZE', 30); 00033 define('QUIZ_REPORT_DEFAULT_GRADING_PAGE_SIZE', 10); 00034 00035 define('QUIZ_REPORT_ATTEMPTS_ALL', 0); 00036 define('QUIZ_REPORT_ATTEMPTS_STUDENTS_WITH_NO', 1); 00037 define('QUIZ_REPORT_ATTEMPTS_STUDENTS_WITH', 2); 00038 define('QUIZ_REPORT_ATTEMPTS_ALL_STUDENTS', 3); 00039 00053 function quiz_report_index_by_keys($datum, $keys, $keysunique = true) { 00054 if (!$datum) { 00055 return array(); 00056 } 00057 $key = array_shift($keys); 00058 $datumkeyed = array(); 00059 foreach ($datum as $data) { 00060 if ($keys || !$keysunique) { 00061 $datumkeyed[$data->{$key}][]= $data; 00062 } else { 00063 $datumkeyed[$data->{$key}]= $data; 00064 } 00065 } 00066 if ($keys) { 00067 foreach ($datumkeyed as $datakey => $datakeyed) { 00068 $datumkeyed[$datakey] = quiz_report_index_by_keys($datakeyed, $keys, $keysunique); 00069 } 00070 } 00071 return $datumkeyed; 00072 } 00073 00074 function quiz_report_unindex($datum) { 00075 if (!$datum) { 00076 return $datum; 00077 } 00078 $datumunkeyed = array(); 00079 foreach ($datum as $value) { 00080 if (is_array($value)) { 00081 $datumunkeyed = array_merge($datumunkeyed, quiz_report_unindex($value)); 00082 } else { 00083 $datumunkeyed[] = $value; 00084 } 00085 } 00086 return $datumunkeyed; 00087 } 00088 00095 function quiz_report_get_significant_questions($quiz) { 00096 global $DB; 00097 00098 $questionids = quiz_questions_in_quiz($quiz->questions); 00099 if (empty($questionids)) { 00100 return array(); 00101 } 00102 00103 list($usql, $params) = $DB->get_in_or_equal(explode(',', $questionids)); 00104 $params[] = $quiz->id; 00105 $questions = $DB->get_records_sql(" 00106 SELECT 00107 q.id, 00108 q.length, 00109 qqi.grade AS maxmark 00110 00111 FROM {question} q 00112 JOIN {quiz_question_instances} qqi ON qqi.question = q.id 00113 00114 WHERE 00115 q.id $usql AND 00116 qqi.quiz = ? AND 00117 length > 0", $params); 00118 00119 $qsbyslot = array(); 00120 $number = 1; 00121 foreach (explode(',', $questionids) as $key => $id) { 00122 if (!array_key_exists($id, $questions)) { 00123 continue; 00124 } 00125 00126 $slot = $key + 1; 00127 $question = $questions[$id]; 00128 $question->slot = $slot; 00129 $question->number = $number; 00130 00131 $qsbyslot[$slot] = $question; 00132 00133 $number += $question->length; 00134 } 00135 00136 return $qsbyslot; 00137 } 00138 00144 function quiz_report_qm_filter_select($quiz, $quizattemptsalias = 'quiza') { 00145 if ($quiz->attempts == 1) { // Only one attempt allowed on this quiz 00146 return ''; 00147 } 00148 00149 switch ($quiz->grademethod) { 00150 case QUIZ_GRADEHIGHEST : 00151 return "$quizattemptsalias.id = ( 00152 SELECT MIN(qa2.id) 00153 FROM {quiz_attempts} qa2 00154 WHERE qa2.quiz = $quizattemptsalias.quiz AND 00155 qa2.userid = $quizattemptsalias.userid AND 00156 COALESCE(qa2.sumgrades, 0) = ( 00157 SELECT MAX(COALESCE(qa3.sumgrades, 0)) 00158 FROM {quiz_attempts} qa3 00159 WHERE qa3.quiz = $quizattemptsalias.quiz AND 00160 qa3.userid = $quizattemptsalias.userid 00161 ) 00162 )"; 00163 00164 case QUIZ_GRADEAVERAGE : 00165 return ''; 00166 00167 case QUIZ_ATTEMPTFIRST : 00168 return "$quizattemptsalias.id = ( 00169 SELECT MIN(qa2.id) 00170 FROM {quiz_attempts} qa2 00171 WHERE qa2.quiz = $quizattemptsalias.quiz AND 00172 qa2.userid = $quizattemptsalias.userid)"; 00173 00174 case QUIZ_ATTEMPTLAST : 00175 return "$quizattemptsalias.id = ( 00176 SELECT MAX(qa2.id) 00177 FROM {quiz_attempts} qa2 00178 WHERE qa2.quiz = $quizattemptsalias.quiz AND 00179 qa2.userid = $quizattemptsalias.userid)"; 00180 } 00181 } 00182 00191 function quiz_report_grade_bands($bandwidth, $bands, $quizid, $userids = array()) { 00192 global $DB; 00193 00194 if ($userids) { 00195 list($usql, $params) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED, 'u'); 00196 $usql = "qg.userid $usql AND"; 00197 } else { 00198 $usql = ''; 00199 $params = array(); 00200 } 00201 $sql = " 00202 SELECT band, COUNT(1) 00203 00204 FROM ( 00205 SELECT FLOOR(qg.grade / :bandwidth) AS band 00206 FROM {quiz_grades} qg 00207 WHERE $usql qg.quiz = :quizid 00208 ) subquery 00209 00210 GROUP BY 00211 band 00212 00213 ORDER BY 00214 band"; 00215 00216 $params['quizid'] = $quizid; 00217 $params['bandwidth'] = $bandwidth; 00218 00219 $data = $DB->get_records_sql_menu($sql, $params); 00220 00221 //need to create array elements with values 0 at indexes where there is no element 00222 $data = $data + array_fill(0, $bands+1, 0); 00223 ksort($data); 00224 00225 //place the maximum (prefect grade) into the last band i.e. make last 00226 //band for example 9 <= g <=10 (where 10 is the perfect grade) rather than 00227 //just 9 <= g <10. 00228 $data[$bands - 1] += $data[$bands]; 00229 unset($data[$bands]); 00230 00231 return $data; 00232 } 00233 00234 function quiz_report_highlighting_grading_method($quiz, $qmsubselect, $qmfilter) { 00235 if ($quiz->attempts == 1) { 00236 return '<p>' . get_string('onlyoneattemptallowed', 'quiz_overview') . '</p>'; 00237 00238 } else if (!$qmsubselect) { 00239 return '<p>' . get_string('allattemptscontributetograde', 'quiz_overview') . '</p>'; 00240 00241 } else if ($qmfilter) { 00242 return '<p>' . get_string('showinggraded', 'quiz_overview') . '</p>'; 00243 00244 } else { 00245 return '<p>' . get_string('showinggradedandungraded', 'quiz_overview', 00246 '<span class="gradedattempt">' . quiz_get_grading_option_name($quiz->grademethod) . 00247 '</span>') . '</p>'; 00248 } 00249 } 00250 00259 function quiz_report_feedback_for_grade($grade, $quizid, $context) { 00260 global $DB; 00261 00262 static $feedbackcache = array(); 00263 00264 if (!isset($feedbackcache[$quizid])) { 00265 $feedbackcache[$quizid] = $DB->get_records('quiz_feedback', array('quizid' => $quizid)); 00266 } 00267 00268 // With CBM etc, it is possible to get -ve grades, which would then not match 00269 // any feedback. Therefore, we replace -ve grades with 0. 00270 $grade = max($grade, 0); 00271 00272 $feedbacks = $feedbackcache[$quizid]; 00273 $feedbackid = 0; 00274 $feedbacktext = ''; 00275 $feedbacktextformat = FORMAT_MOODLE; 00276 foreach ($feedbacks as $feedback) { 00277 if ($feedback->mingrade <= $grade && $grade < $feedback->maxgrade) { 00278 $feedbackid = $feedback->id; 00279 $feedbacktext = $feedback->feedbacktext; 00280 $feedbacktextformat = $feedback->feedbacktextformat; 00281 break; 00282 } 00283 } 00284 00285 // Clean the text, ready for display. 00286 $formatoptions = new stdClass(); 00287 $formatoptions->noclean = true; 00288 $feedbacktext = file_rewrite_pluginfile_urls($feedbacktext, 'pluginfile.php', 00289 $context->id, 'mod_quiz', 'feedback', $feedbackid); 00290 $feedbacktext = format_text($feedbacktext, $feedbacktextformat, $formatoptions); 00291 00292 return $feedbacktext; 00293 } 00294 00301 function quiz_report_scale_summarks_as_percentage($rawmark, $quiz, $round = true) { 00302 if ($quiz->sumgrades == 0) { 00303 return ''; 00304 } 00305 if (!is_numeric($rawmark)) { 00306 return $rawmark; 00307 } 00308 00309 $mark = $rawmark * 100 / $quiz->sumgrades; 00310 if ($round) { 00311 $mark = quiz_format_grade($quiz, $mark); 00312 } 00313 return $mark . '%'; 00314 } 00315 00320 function quiz_report_list($context) { 00321 global $DB; 00322 static $reportlist = null; 00323 if (!is_null($reportlist)) { 00324 return $reportlist; 00325 } 00326 00327 $reports = $DB->get_records('quiz_reports', null, 'displayorder DESC', 'name, capability'); 00328 $reportdirs = get_plugin_list('quiz'); 00329 00330 // Order the reports tab in descending order of displayorder 00331 $reportcaps = array(); 00332 foreach ($reports as $key => $report) { 00333 if (array_key_exists($report->name, $reportdirs)) { 00334 $reportcaps[$report->name] = $report->capability; 00335 } 00336 } 00337 00338 // Add any other reports, which are on disc but not in the DB, on the end 00339 foreach ($reportdirs as $reportname => $notused) { 00340 if (!isset($reportcaps[$reportname])) { 00341 $reportcaps[$reportname] = null; 00342 } 00343 } 00344 $reportlist = array(); 00345 foreach ($reportcaps as $name => $capability) { 00346 if (empty($capability)) { 00347 $capability = 'mod/quiz:viewreports'; 00348 } 00349 if (has_capability($capability, $context)) { 00350 $reportlist[] = $name; 00351 } 00352 } 00353 return $reportlist; 00354 } 00355 00365 function quiz_report_download_filename($report, $courseshortname, $quizname) { 00366 return $courseshortname . '-' . format_string($quizname, true) . '-' . $report; 00367 } 00368 00373 function quiz_report_default_report($context) { 00374 return reset(quiz_report_list($context)); 00375 } 00376 00385 function quiz_no_questions_message($quiz, $cm, $context) { 00386 global $OUTPUT; 00387 00388 $output = ''; 00389 $output .= $OUTPUT->notification(get_string('noquestions', 'quiz')); 00390 if (has_capability('mod/quiz:manage', $context)) { 00391 $output .= $OUTPUT->single_button(new moodle_url('/mod/quiz/edit.php', 00392 array('cmid' => $cm->id)), get_string('editquiz', 'quiz'), 'get'); 00393 } 00394 00395 return $output; 00396 }