MDL-20636 Finished conversion of the manual grading report.
[moodle.git] / mod / quiz / report / responses / responses_table.php
CommitLineData
aeb15530 1<?php
e84cb615 2define ('QUIZ_REPORT_RESPONSES_MAX_LEN_TO_DISPLAY', 150);
7f29a7db 3
4class quiz_report_responses_table extends table_sql {
5
6 var $useridfield = 'userid';
7
8 var $reporturl;
9 var $displayoptions;
10
11 function quiz_report_responses_table($quiz , $qmsubselect, $groupstudents,
8ad67658 12 $students, $questions, $candelete, $reporturl, $displayoptions, $context){
7f29a7db 13 parent::table_sql('mod-quiz-report-responses-report');
14 $this->quiz = $quiz;
15 $this->qmsubselect = $qmsubselect;
16 $this->groupstudents = $groupstudents;
17 $this->students = $students;
18 $this->questions = $questions;
19 $this->candelete = $candelete;
20 $this->reporturl = $reporturl;
21 $this->displayoptions = $displayoptions;
8ad67658 22 $this->context = $context;
7f29a7db 23 }
24 function build_table(){
7f29a7db 25 if ($this->rawdata) {
3b518020 26 $this->strtimeformat = str_replace(',', ' ', get_string('strftimedatetime'));
7f29a7db 27 parent::build_table();
7f29a7db 28 }
29 }
30
31 function wrap_html_start(){
32 if (!$this->is_downloading()) {
33 if ($this->candelete) {
34 // Start form
6ea66ff3 35 $displayurl = new moodle_url($this->reporturl, $this->displayoptions);
7f29a7db 36 $strreallydel = addslashes_js(get_string('deleteattemptcheck','quiz'));
37 echo '<div id="tablecontainer">';
eb788065 38 echo '<form id="attemptsform" method="post" action="' . $displayurl->out_omit_querystring() .
7f29a7db 39 '" onsubmit="confirm(\''.$strreallydel.'\');">';
40 echo '<div style="display: none;">';
6ea66ff3 41 echo html_writer::input_hidden_params($displayurl);
db77f410 42 echo html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey())) . "\n";
7f29a7db 43 echo '</div>';
44 echo '<div>';
45 }
46 }
47 }
48 function wrap_html_finish(){
49 if (!$this->is_downloading()) {
50 // Print "Select all" etc.
51 if ($this->candelete) {
670b8954 52 echo '<div id="commands">';
7f29a7db 53 echo '<a href="javascript:select_all_in(\'DIV\',null,\'tablecontainer\');">'.
54 get_string('selectall', 'quiz').'</a> / ';
55 echo '<a href="javascript:deselect_all_in(\'DIV\',null,\'tablecontainer\');">'.
56 get_string('selectnone', 'quiz').'</a> ';
57 echo '&nbsp;&nbsp;';
6559096f 58 echo '<input type="submit" value="'.get_string('deleteselected', 'quiz_overview').'"/>';
670b8954 59 echo '</div>';
7f29a7db 60 // Close form
61 echo '</div>';
62 echo '</form></div>';
63 }
64 }
65 }
66
67
68 function col_checkbox($attempt){
69 if ($attempt->attempt){
70 return '<input type="checkbox" name="attemptid[]" value="'.$attempt->attempt.'" />';
71 } else {
72 return '';
73 }
74 }
75
76 function col_picture($attempt){
39e37019 77 global $COURSE, $OUTPUT;
39790bd8 78 $user = new stdClass();
35bf6352 79 $user->id = $attempt->userid;
80 $user->lastname = $attempt->lastname;
81 $user->firstname = $attempt->firstname;
82 $user->imagealt = $attempt->imagealt;
83 $user->picture = $attempt->picture;
3a11c09f 84 $user->email = $attempt->email;
812dbaf7 85 return $OUTPUT->user_picture($user);
7f29a7db 86 }
87
65778323
TH
88 function col_fullname($attempt){
89 $html = parent::col_fullname($attempt);
90 if ($this->is_downloading()) {
91 return $html;
92 }
93
94 return $html . '<br /><a class="reviewlink" href="review.php?q='.$this->quiz->id.'&amp;attempt='.$attempt->attempt.
95 '">'.get_string('reviewattempt', 'quiz').'</a>';
96 }
7f29a7db 97
98 function col_timestart($attempt){
99 if ($attempt->attempt) {
100 $startdate = userdate($attempt->timestart, $this->strtimeformat);
101 if (!$this->is_downloading()) {
102 return '<a href="review.php?q='.$this->quiz->id.'&amp;attempt='.$attempt->attempt.'">'.$startdate.'</a>';
103 } else {
104 return $startdate;
105 }
106 } else {
107 return '-';
108 }
109 }
110 function col_timefinish($attempt){
111 if ($attempt->attempt) {
112 if ($attempt->timefinish) {
113 $timefinish = userdate($attempt->timefinish, $this->strtimeformat);
114 if (!$this->is_downloading()) {
115 return '<a href="review.php?q='.$this->quiz->id.'&amp;attempt='.$attempt->attempt.'">'.$timefinish.'</a>';
116 } else {
117 return $timefinish;
118 }
119 } else {
120 return '-';
121 }
122 } else {
123 return '-';
124 }
125 }
126
127 function col_duration($attempt){
128 if ($attempt->timefinish) {
ea906bb4 129 return format_time($attempt->timefinish - $attempt->timestart);
7f29a7db 130 } elseif ($attempt->timestart) {
131 return get_string('unfinished', 'quiz');
132 } else {
133 return '-';
134 }
135 }
ea906bb4 136
7f29a7db 137 function col_sumgrades($attempt){
65778323 138 if (!$attempt->timefinish) {
7f29a7db 139 return '-';
140 }
65778323
TH
141
142 $grade = quiz_rescale_grade($attempt->sumgrades, $this->quiz);
143 if ($this->is_downloading()) {
144 return $grade;
145 }
146
147 $gradehtml = '<a href="review.php?q='.$this->quiz->id.'&amp;attempt='.$attempt->attempt.
148 '" title="'.get_string('reviewattempt', 'quiz').'">'.$grade.'</a>';
149 if ($this->qmsubselect && $attempt->gradedattempt){
150 $gradehtml = '<div class="highlight">'.$gradehtml.'</div>';
151 }
152 return $gradehtml;
7f29a7db 153 }
65778323 154
7f29a7db 155 function other_cols($colname, $attempt){
ca4b4f8f 156 global $QTYPES, $OUTPUT;
3e71541f 157 static $states =array();
7f29a7db 158 if (preg_match('/^qsanswer([0-9]+)$/', $colname, $matches)){
3f8e526e 159 if ($attempt->uniqueid == 0) {
160 return '-';
161 }
7f29a7db 162 $questionid = $matches[1];
2ea2c1f5 163 if (isset($this->gradedstatesbyattempt[$attempt->uniqueid][$questionid])){
164 $stateforqinattempt = $this->gradedstatesbyattempt[$attempt->uniqueid][$questionid];
165 } else {
166 return '-';
167 }
aeb15530 168
7f29a7db 169 $question = $this->questions[$questionid];
2ea2c1f5 170 restore_question_state($question, $stateforqinattempt);
aeb15530 171
2280e147 172 if (!$this->is_downloading() || $this->is_downloading() == 'xhtml'){
173 $formathtml = true;
8968f51f 174 } else {
2280e147 175 $formathtml = false;
8968f51f 176 }
ca4b4f8f 177
2280e147 178 $summary = $QTYPES[$question->qtype]->response_summary($question, $stateforqinattempt,
179 QUIZ_REPORT_RESPONSES_MAX_LEN_TO_DISPLAY, $formathtml);
7f29a7db 180 if (!$this->is_downloading()) {
2280e147 181 if ($summary){
9bf16314
PS
182 $link = new moodle_url("/mod/quiz/reviewquestion.php?attempt=$attempt->attempt&question=$question->id");
183 $action = new popup_action('click', $link, 'reviewquestion', array('height' => 450, 'width' => 650));
65778323 184 $summary = $OUTPUT->action_link($link, $summary, $action, array('title'=>get_string('reviewresponsetoq', 'quiz', $question->formattedname)));
ca4b4f8f 185
8968f51f 186 if (question_state_is_graded($stateforqinattempt)
26da840f 187 && ($question->maxgrade > 0)){
8968f51f 188 $grade = $stateforqinattempt->grade
2280e147 189 / $question->maxgrade;
8968f51f 190 $qclass = question_get_feedback_class($grade);
191 $feedbackimg = question_get_feedback_image($grade);
192 $questionclass = "que";
2280e147 193 return "<span class=\"$questionclass\"><span class=\"$qclass\">".$summary."</span></span>$feedbackimg";
e1d2278b 194 } else {
2280e147 195 return $summary;
e1d2278b 196 }
7f29a7db 197 } else {
199b946f 198 return '';
199 }
aeb15530 200
7f29a7db 201 } else {
2280e147 202 return $summary;
7f29a7db 203 }
204 } else {
205 return NULL;
206 }
207 }
208
209 function col_feedbacktext($attempt){
210 if ($attempt->timefinish) {
211 if (!$this->is_downloading()) {
8ad67658 212 return quiz_report_feedback_for_grade(quiz_rescale_grade($attempt->sumgrades, $this->quiz, false), $this->quiz->id, $this->context);
7f29a7db 213 } else {
8ad67658 214 return strip_tags(quiz_report_feedback_for_grade(quiz_rescale_grade($attempt->sumgrades, $this->quiz, false), $this->quiz->id, $this->context));
7f29a7db 215 }
216 } else {
217 return '-';
218 }
219
220 }
221
222 function query_db($pagesize, $useinitialsbar=true){
223 // Add table joins so we can sort by question answer
224 // unfortunately can't join all tables necessary to fetch all answers
225 // to get the state for one question per attempt row we must join two tables
226 // and there is a limit to how many joins you can have in one query. In MySQL it
227 // is 61. This means that when having more than 29 questions the query will fail.
228 // So we join just the tables needed to sort the attempts.
229 if($sort = $this->get_sql_sort()) {
230 $this->sql->from .= ' ';
231 $sortparts = explode(',', $sort);
232 $matches = array();
233 foreach($sortparts as $sortpart) {
234 $sortpart = trim($sortpart);
235 if (preg_match('/^qsanswer([0-9]+)/', $sortpart, $matches)){
236 $qid = intval($matches[1]);
237 $this->sql->fields .= ", qs$qid.grade AS qsgrade$qid, qs$qid.answer AS qsanswer$qid, qs$qid.event AS qsevent$qid, qs$qid.id AS qsid$qid";
238 $this->sql->from .= "LEFT JOIN {question_sessions} qns$qid ON qns$qid.attemptid = qa.uniqueid AND qns$qid.questionid = :qid$qid ";
239 $this->sql->from .= "LEFT JOIN {question_states} qs$qid ON qs$qid.id = qns$qid.newgraded ";
240 $this->sql->params['qid'.$qid] = $qid;
241 }
242 }
243 }
244 parent::query_db($pagesize, $useinitialsbar);
2ea2c1f5 245 $qsfields = 'qs.id, qs.grade, qs.event, qs.question, qs.answer, qs.attempt';
246 if (!$this->is_downloading()) {
247 $attemptids = array();
248 foreach ($this->rawdata as $attempt){
249 if ($attempt->uniqueid > 0){
250 $attemptids[] = $attempt->uniqueid;
251 }
252 }
253 $this->gradedstatesbyattempt = quiz_get_newgraded_states($attemptids, true, $qsfields);
254 } else {
255 $this->gradedstatesbyattempt = quiz_get_newgraded_states($this->sql, true, $qsfields);
256 }
7f29a7db 257 }
258}
aeb15530 259