MDL-15350
[moodle.git] / mod / quiz / report / overview / overview_table.php
CommitLineData
c35f3afc 1<?php // $Id$
2
3class quiz_report_overview_table extends table_sql {
9cf4a18b 4
c35f3afc 5 var $useridfield = 'userid';
9cf4a18b 6
c35f3afc 7 var $candelete;
8 var $reporturl;
9 var $displayoptions;
9cf4a18b 10
c35f3afc 11 function quiz_report_overview_table($quiz , $qmsubselect, $groupstudents,
12 $students, $detailedmarks, $questions, $candelete, $reporturl, $displayoptions){
13 parent::table_sql('mod-quiz-report-overview-report');
14 $this->quiz = $quiz;
15 $this->qmsubselect = $qmsubselect;
16 $this->groupstudents = $groupstudents;
17 $this->students = $students;
18 $this->detailedmarks = $detailedmarks;
19 $this->questions = $questions;
20 $this->candelete = $candelete;
21 $this->reporturl = $reporturl;
22 $this->displayoptions = $displayoptions;
23 }
24 function build_table(){
9cf4a18b 25 global $CFG, $DB;
c35f3afc 26 if ($this->rawdata) {
27 // Define some things we need later to process raw data from db.
28 $this->strtimeformat = get_string('strftimedatetime');
29 parent::build_table();
30 //end of adding data from attempts data to table / download
31 //now add averages at bottom of table :
9cf4a18b 32 $params = array($this->quiz->id);
c35f3afc 33 $averagesql = "SELECT AVG(qg.grade) AS grade " .
9cf4a18b 34 "FROM {quiz_grades} qg " .
35 "WHERE quiz=?";
36
c35f3afc 37 $this->add_separator();
38 if ($this->is_downloading()){
39 $namekey = 'lastname';
40 } else {
41 $namekey = 'fullname';
42 }
43 if ($this->groupstudents){
8673a566 44 list($g_usql, $g_params) = $DB->get_in_or_equal($this->groupstudents);
9cf4a18b 45
46 $groupaveragesql = $averagesql." AND qg.userid $g_usql";
47 $groupaverage = $DB->get_record_sql($groupaveragesql, array_merge($params, $g_params));
c35f3afc 48 $groupaveragerow = array($namekey => get_string('groupavg', 'grades'),
49 'sumgrades' => round($groupaverage->grade, $this->quiz->decimalpoints),
50 'feedbacktext'=> strip_tags(quiz_report_feedback_for_grade($groupaverage->grade, $this->quiz->id)));
51 if($this->detailedmarks && $this->qmsubselect) {
52 $avggradebyq = quiz_get_average_grade_for_questions($this->quiz, $this->groupstudents);
53 $groupaveragerow += quiz_format_average_grade_for_questions($avggradebyq, $this->questions, $this->quiz, $this->is_downloading());
54 }
55 $this->add_data_keyed($groupaveragerow);
56 }
9cf4a18b 57
8673a566 58 list($s_usql, $s_params) = $DB->get_in_or_equal($this->students);
9cf4a18b 59 $overallaverage = $DB->get_record_sql($averagesql." AND qg.userid $s_usql", array_merge($params, $s_params));
c35f3afc 60 $overallaveragerow = array($namekey => get_string('overallaverage', 'grades'),
61 'sumgrades' => round($overallaverage->grade, $this->quiz->decimalpoints),
62 'feedbacktext'=> strip_tags(quiz_report_feedback_for_grade($overallaverage->grade, $this->quiz->id)));
63 if($this->detailedmarks && $this->qmsubselect) {
64 $avggradebyq = quiz_get_average_grade_for_questions($this->quiz, $this->students);
65 $overallaveragerow += quiz_format_average_grade_for_questions($avggradebyq, $this->questions, $this->quiz, $this->is_downloading());
66 }
67 $this->add_data_keyed($overallaveragerow);
68 }
69 }
9cf4a18b 70
c35f3afc 71 function wrap_html_start(){
72 if (!$this->is_downloading()) {
73 if ($this->candelete) {
74 // Start form
75 $strreallydel = addslashes_js(get_string('deleteattemptcheck','quiz'));
76 echo '<div id="tablecontainer">';
77 echo '<form id="attemptsform" method="post" action="' . $this->reporturl->out(true) .
78 '" onsubmit="confirm(\''.$strreallydel.'\');">';
5bb614fe 79 echo '<div style="display: none;">';
c35f3afc 80 echo $this->reporturl->hidden_params_out(array(), 0, $this->displayoptions);
5bb614fe 81 echo '</div>';
c35f3afc 82 echo '<div>';
83 }
84 }
85 }
86 function wrap_html_finish(){
87 if (!$this->is_downloading()) {
88 // Print "Select all" etc.
89 if ($this->candelete) {
90 echo '<table id="commands">';
91 echo '<tr><td>';
92 echo '<a href="javascript:select_all_in(\'DIV\',null,\'tablecontainer\');">'.
93 get_string('selectall', 'quiz').'</a> / ';
94 echo '<a href="javascript:deselect_all_in(\'DIV\',null,\'tablecontainer\');">'.
95 get_string('selectnone', 'quiz').'</a> ';
96 echo '&nbsp;&nbsp;';
97 echo '<input type="submit" value="'.get_string('deleteselected', 'quiz_overview').'"/>';
98 echo '</td></tr></table>';
99 // Close form
100 echo '</div>';
101 echo '</form></div>';
102 }
103 }
104 }
105
9cf4a18b 106
c35f3afc 107 function col_checkbox($attempt){
108 if ($attempt->attempt){
109 return '<input type="checkbox" name="attemptid[]" value="'.$attempt->attempt.'" />';
110 } else {
111 return '';
112 }
113 }
9cf4a18b 114
c35f3afc 115 function col_picture($attempt){
116 global $COURSE;
117 return print_user_picture($attempt->userid, $COURSE->id, $attempt->picture, false, true);
118 }
119
9cf4a18b 120
c35f3afc 121 function col_timestart($attempt){
122 if ($attempt->attempt) {
123 $startdate = userdate($attempt->timestart, $this->strtimeformat);
124 if (!$this->is_downloading()) {
125 return '<a href="review.php?q='.$this->quiz->id.'&amp;attempt='.$attempt->attempt.'">'.$startdate.'</a>';
126 } else {
127 return $startdate;
128 }
129 } else {
130 return '-';
131 }
132 }
133 function col_timefinish($attempt){
134 if ($attempt->attempt) {
135 if ($attempt->timefinish) {
136 $timefinish = userdate($attempt->timefinish, $this->strtimeformat);
137 if (!$this->is_downloading()) {
138 return '<a href="review.php?q='.$this->quiz->id.'&amp;attempt='.$attempt->attempt.'">'.$timefinish.'</a>';
139 } else {
140 return $timefinish;
141 }
142 } else {
143 return '-';
144 }
145 } else {
146 return '-';
147 }
148 }
9cf4a18b 149
c35f3afc 150 function col_duration($attempt){
151 if ($attempt->timefinish) {
152 return format_time($attempt->duration);
153 } elseif ($attempt->timestart) {
154 return get_string('unfinished', 'quiz');
155 } else {
156 return '-';
157 }
158 }
159 function col_sumgrades($attempt){
160 if ($attempt->timefinish) {
161 $grade = quiz_rescale_grade($attempt->sumgrades, $this->quiz);
162 if (!$this->is_downloading()) {
163 $gradehtml = '<a href="review.php?q='.$this->quiz->id.'&amp;attempt='.$attempt->attempt.'">'.$grade.'</a>';
164 if ($this->qmsubselect && $attempt->gradedattempt){
165 $gradehtml = '<div class="highlight">'.$gradehtml.'</div>';
166 }
167 return $gradehtml;
168 } else {
169 return $grade;
170 }
171 } else {
172 return '-';
173 }
174 }
175 function other_cols($colname, $attempt){
181608b7 176 static $gradedstatesbyattempt = null;
177 if ($gradedstatesbyattempt === null){
178 //get all the attempt ids we want to display on this page
179 //or to export for download.
67d4dfb8 180 if (!$this->is_downloading()) {
181 $attemptids = array();
182 foreach ($this->rawdata as $attempt){
183 if ($attempt->attemptuniqueid > 0){
184 $attemptids[] = $attempt->attemptuniqueid;
185 }
181608b7 186 }
67d4dfb8 187 $gradedstatesbyattempt = quiz_get_newgraded_states($attemptids, true, 'qs.id, qs.grade, qs.event, qs.question, qs.attempt');
188 } else {
189 $gradedstatesbyattempt = quiz_get_newgraded_states($this->sql, true, 'qs.id, qs.grade, qs.event, qs.question, qs.attempt');
181608b7 190 }
181608b7 191 }
c35f3afc 192 if (preg_match('/^qsgrade([0-9]+)$/', $colname, $matches)){
193 $questionid = $matches[1];
194 $question = $this->questions[$questionid];
181608b7 195 $stateforqinattempt = $gradedstatesbyattempt[$attempt->attemptuniqueid][$questionid];
196 if (question_state_is_graded($stateforqinattempt)) {
197 $grade = quiz_rescale_grade($stateforqinattempt->grade, $this->quiz);
c35f3afc 198 } else {
199 $grade = '--';
200 }
201 if (!$this->is_downloading()) {
202 $grade = $grade.'/'.quiz_rescale_grade($question->grade, $this->quiz);
203 return link_to_popup_window('/mod/quiz/reviewquestion.php?state='.
181608b7 204 $stateforqinattempt->id.'&amp;number='.$question->number,
c35f3afc 205 'reviewquestion', $grade, 450, 650, get_string('reviewresponse', 'quiz'),
206 'none', true);
207 } else {
208 return $grade;
9cf4a18b 209 }
c35f3afc 210 } else {
211 return NULL;
212 }
213 }
9cf4a18b 214
c35f3afc 215 function col_feedbacktext($attempt){
216 if ($attempt->timefinish) {
217 if (!$this->is_downloading()) {
218 return quiz_report_feedback_for_grade(quiz_rescale_grade($attempt->sumgrades, $this->quiz), $this->quiz->id);
219 } else {
220 return strip_tags(quiz_report_feedback_for_grade(quiz_rescale_grade($attempt->sumgrades, $this->quiz), $this->quiz->id));
221 }
222 } else {
223 return '-';
224 }
9cf4a18b 225
c35f3afc 226 }
8673a566 227
228 function query_db($pagesize, $useinitialsbar=true){
229 // Add table joins so we can sort by question grade
230 // unfortunately can't join all tables necessary to fetch all grades
231 // to get the state for one question per attempt row we must join two tables
232 // and there is a limit to how many joins you can have in one query. In MySQL it
233 // is 61. This means that when having more than 29 questions the query will fail.
234 // So we join just the tables needed to sort the attempts.
235 if($sort = $this->get_sql_sort()) {
236 if ($this->detailedmarks) {
237 $this->sql->from .= ' ';
238 $sortparts = explode(',', $sort);
239 $matches = array();
240 foreach($sortparts as $sortpart) {
241 $sortpart = trim($sortpart);
242 if (preg_match('/^qsgrade([0-9]+)/', $sortpart, $matches)){
243 $qid = intval($matches[1]);
244 $this->sql->fields .= ", qs$qid.grade AS qsgrade$qid, qs$qid.event AS qsevent$qid, qs$qid.id AS qsid$qid";
245 $this->sql->from .= "LEFT JOIN {question_sessions} qns$qid ON qns$qid.attemptid = qa.uniqueid AND qns$qid.questionid = :qid$qid ";
246 $this->sql->from .= "LEFT JOIN {question_states} qs$qid ON qs$qid.id = qns$qid.newgraded ";
247 $this->sql->params['qid'.$qid] = $qid;
248 }
249 }
250 }
251 }
252 parent::query_db($pagesize, $useinitialsbar);
253 }
c35f3afc 254}
255?>