1898666c90586b24f56560d04550924dd7998d34
[moodle.git] / mod / hotpot / index.php
1 <?PHP // $Id$
3 // This page lists all the instances of hotpot in a particular course
5     require_once("../../config.php");
6     require_once("../../course/lib.php");
7     require_once("lib.php");
9     $id = required_param('id', PARAM_INT);   // course    
10     if (! $course = get_record("course", "id", $id)) {
11         error("Course ID is incorrect");
12     }
14     require_login($course->id);
16     $coursecontext = get_context_instance(CONTEXT_COURSE, $id);
17     $sitecontext = get_context_instance(CONTEXT_SYSTEM, SITEID);
19     add_to_log($course->id, "hotpot", "view all", "index.php?id=$course->id", "");
21     // Moodle 1.4+ requires sesskey to be passed in forms
22     if (isset($USER->sesskey)) {
23         $sesskey = '<input type="hidden" name="sesskey" value="'.$USER->sesskey.'" />';
24     } else {
25         $sesskey = '';
26     }
28     // get message strings for titles
29     $strmodulenameplural = get_string("modulenameplural", "hotpot");
30     $strmodulename  = get_string("modulename", "hotpot");
32     // string translation array for single and double quotes
33     $quotes = array("'"=>"\'", '"'=>'&quot;');
35     // Print the header
37     $title = "$course->shortname: $strmodulenameplural";
38     $heading = "$course->fullname";
39     $navigation = "$strmodulenameplural";
40     if ($course->id != SITEID) {
41         $navigation = "<a href=\"../../course/view.php?id=$course->id\">$course->shortname</a> -> $navigation";
42     }
43     print_header($title, $heading, $navigation, "", "", true, "", navmenu($course));
45     $next_url = "$CFG->wwwroot/course/view.php?id=$course->id";
47     // get display section, if any
48     $section = optional_param('section', 0, PARAM_INT);
49     if ($section) {
50         $displaysection = course_set_display($course->id, $section);
51     } else {
52         if (isset($USER->display[$course->id])) {
53             $displaysection = $USER->display[$course->id];
54         } else {
55             $displaysection = 0;
56         }
57     }
59     // Get all hotpot instances in this course
60     $hotpots = array();
61     if ($hotpot_instances = hotpot_get_all_instances_in_course('hotpot', $course)) {
62         foreach ($hotpot_instances as $hotpot_instance) {
63             if ($displaysection>0 && $hotpot_instance->section>0 && $displaysection<>$hotpot_instance->section) {
64                 // do nothing (user is not diplaying this section)
65             } else {
66                 $hotpots[$hotpot_instance->id] = $hotpot_instance;
67             } 
68         }
69     }
70     if (empty($hotpots)) {
71         notice("There are no $strmodulenameplural", $next_url);
72         exit;
73     }
74     $hotpotids = implode(',', array_keys($hotpots));
76     if (has_capability('mod/hotpot:grade', $sitecontext)) {
78         // array of hotpots to be regraded
79         $regrade_hotpots = array();
81         // do we need to regrade any or all of the hotpots?
82         $regrade = optional_param('regrade', 0, PARAM_SEQUENCE);
83         if ($regrade) {
84             // add valid hotpot ids to the regrade array
85             $regrade = explode(',', $regrade);
86             foreach ($regrade as $id) {
87                 if (isset($hotpots[$id])) {
88                     $regrade_hotpots[$id] = &$hotpots[$id];
89                 }
90             }
91             $regrade = implode(',', array_keys($regrade_hotpots));
92         }
93         if ($regrade) {
95             $confirm = optional_param('confirm', 0, PARAM_BOOL);
96             if (!$confirm) {
98                 print_simple_box_start("center", "60%", "#FFAAAA", 20, "noticebox");
100                 if (count($regrade_hotpots)==1) {
101                     print_heading(get_string('regradecheck', 'hotpot', $regrade_hotpots[$regrade]->name));
102                 } else {
103                     print_heading(get_string('regradecheck', 'hotpot', ''));
104                     print '<ul>';
105                     foreach ($regrade_hotpots as $hotpot) {
106                         print "<li>$hotpot->name</li>";
107                     }
108                     print '</ul>';
109                 }
110                 print ''
111                 .   '<div align="center"><table border="0"><tr><td>'
112                 .   '<form target="_parent" method="post" action="'.$ME.'">'
113                 .   '<input type="hidden" name="id" value="'.$course->id.'">'
114                 .   '<input type="hidden" name="regrade" value="'.$regrade.'" />'
115                 .   '<input type="hidden" name="confirm" value="1" />'
116                 .   $sesskey
117                 .   '<input type="submit" value="'.get_string("yes").'" />'
118                 .   '</form>'
119                 .   '</td><td> &nbsp; </td><td>'
120                 .   '<form target="_parent" method="post" action="'.$ME.'">'
121                 .   '<input type="hidden" name="id" value="'.$course->id.'">'
122                 .   $sesskey
123                 .   '<input type="submit" value="'.get_string("no").'" />'
124                 .   '</form>'
125                 .   '</td></tr></table></div>'
126                 ;
128                 print_simple_box_end();
129                 print_footer($course);
130                 exit;
132             } else { // regrade has been confirmed, so proceed
134                 // start hotpot counter and timer
135                 $hotpotstart = microtime();
136                 $hotpotcount = 0;
138                 // regrade attempts for these hotpots
139                 foreach ($regrade_hotpots as $hotpot) {
140                     notify("<b>$hotpot->name</b>");
142                     // delete questions and responses for this hotpot
143                     if ($records = get_records_select('hotpot_questions', "hotpot=$hotpot->id", '', 'id,hotpot')) {
144                         $questionids = implode(',', array_keys($records));
145                         hotpot_delete_and_notify('hotpot_questions', "id IN ($questionids)", get_string('question', 'quiz'));
146                         hotpot_delete_and_notify('hotpot_responses', "question IN ($questionids)", get_string('answer', 'quiz'));
147                     }
149                     // start attempt counter and timer
150                     $attemptstart = microtime();
151                     $attemptcount = 0;
153                     // regrade attempts, if any, for this hotpot
154                     if ($attempts = get_records_select('hotpot_attempts', "hotpot=$hotpot->id")) {
155                         foreach ($attempts as $attempt) {
156                             $attempt->details = get_field('hotpot_details', 'details', 'attempt', $attempt->id);
157                             if ($attempt->details) {
158                                 hotpot_add_attempt_details($attempt);
159                                 if (! update_record('hotpot_attempts', $attempt)) {
160                                     error("Could not update attempt record: ".$db->ErrorMsg(), $next_url);
161                                 }
162                             }
163                             $attemptcount++;
164                         }
165                     }
166                     if ($attemptcount) {
167                         $msg = get_string('added', 'moodle', "$attemptcount x ".get_string('attempts', 'quiz'));
168                         if (!empty($CFG->hotpot_showtimes)) {
169                             $msg .= ' ('.format_time(sprintf("%0.2f", microtime_diff($attemptstart, microtime()))).')';
170                         }
171                         notify($msg);
172                     }
173                     $hotpotcount++;
174                 } // end foreach $hotpots
175                 if ($hotpotcount) {
176                     $msg = get_string('regrade', 'quiz').": $hotpotcount x ".get_string('modulenameplural', 'hotpot');
177                     if (!empty($CFG->hotpot_showtimes)) {
178                         $msg .= ' ('.format_time(sprintf("%0.2f", microtime_diff($hotpotstart, microtime()))).')';
179                     }
180                     notify($msg);
181                 }
182                 notify(get_string('regradecomplete', 'quiz'));
183             } // end if $confirm
184         } // end regrade
186         // get duplicate hotpot-name questions
187         //  - JMatch LHS is longer than 255 bytes
188         //  - JQuiz question text is longer than 255 bytes
189         //  - other unidentified situations ?!
191         $regrade_hotpots = array();
192         $concat_field = sql_concat('hotpot', "'_'", 'name');
193         if ($concat_field) {
194             $records = get_records_sql("
195                 SELECT $concat_field, COUNT(*), hotpot, name
196                 FROM {$CFG->prefix}hotpot_questions 
197                 WHERE hotpot IN ($hotpotids)
198                 GROUP BY hotpot, name 
199                 HAVING COUNT(*) >1
200             ");
201             if ($records) {
202                 foreach ($records as $record) {
203                     $regrade_hotpots[$record->hotpot] = 1;
204                 }
205                 ksort($regrade_hotpots);
206                 $regrade_hotpots = array_keys($regrade_hotpots);
207             }
208         }
209     }
211     // start timer
212     $start = microtime();
214     // get total number of attempts, users and details for these hotpots
215     $tables = "{$CFG->prefix}hotpot_attempts a";
216     $fields = "
217         a.hotpot AS hotpot,
218         COUNT(DISTINCT a.clickreportid) AS attemptcount,
219         COUNT(DISTINCT a.userid) AS usercount,
220         MAX(a.score) AS maxscore
221     ";
222     $select = "a.hotpot IN ($hotpotids)";
223     if (has_capability('mod/hotpot:viewreport', $coursecontext)) {
224         // do nothing (=get all users)
225     } else {
226         // restrict results to this user only
227         $select .= " AND a.userid='$USER->id'";
228     }
229     $usejoin = 0;
230     if (has_capability('mod/hotpot:grade', get_context_instance(CONTEXT_SYSTEM, SITEID)) && $usejoin) {
231         // join attempts table and details table
232         $tables .= ",{$CFG->prefix}hotpot_details d";
233         $fields .= ',COUNT(DISTINCT d.id) AS detailcount';
234         $select .= " AND a.id=d.attempt";
236         // this may take about twice as long as getting the gradecounts separately :-(
237         // so this operation could be done after getting the $totals from the attempts table
238     }
239     $totals = get_records_sql("SELECT $fields FROM $tables WHERE $select GROUP BY a.hotpot");
241     if (has_capability('mod/hotpot:grade', get_context_instance(CONTEXT_SYSTEM, SITEID)) && empty($usejoin)) {
242         foreach ($hotpots as $hotpot) {
243             $totals[$hotpot->id]->detailcount = 0;
244             if ($ids = get_records('hotpot_attempts', 'hotpot', $hotpot->id)) {
245                 $ids = join(',', array_keys($ids));
246                 $totals[$hotpot->id]->detailcount = count_records_select('hotpot_details', "attempt IN ($ids)");
247             }
248         }
249     }
251     // message strings for main table
252     $strusers  = get_string('users');
253     $strupdate = get_string('update');
254     $strregrade = get_string('regrade', 'hotpot');
255     $strneverclosed = get_string('neverclosed', 'hotpot');
256     $strregraderequired = get_string('regraderequired', 'hotpot');
258     // column headings and attributes
259     $table->head = array();
260     $table->align = array();
262     if (!empty($CFG->hotpot_showtimes)) {
263         print '<H3>'.sprintf("%0.3f", microtime_diff($start, microtime())).' secs'."</H3>\n";
264     }
266     switch ($course->format) {
267         case 'weeks' : 
268             $title = get_string("week");
269             break;
270         case 'topics' : 
271             $title = get_string("topic");
272             break;
273         default : 
274             $title = '';
275             break;
276     }
277     if ($title) {
278         array_push($table->head, $title); 
279         array_push($table->align, "center");
280     }
281     if (has_capability('moodle/course:manageactivities', $coursecontext)) {
282         array_push($table->head, $strupdate);
283         array_push($table->align, "center");
284     }
285     array_push($table->head, 
286         get_string("name"), 
287         get_string("quizcloses", "quiz"), 
288         get_string("bestgrade", "quiz"), 
289         get_string("attempts", "quiz")
290     );
291     array_push($table->align, 
292         "left", "left", "center", "left"
293     );
294     if (has_capability('mod/hotpot:grade', $coursecontext)) {
295         array_push($table->head, $strregrade);
296         array_push($table->align, "center");
297     }
299     $currentsection = -1;
300     foreach ($hotpots as $hotpot) {
302         $printsection = "";
303         if ($hotpot->section != $currentsection) {
304             if ($hotpot->section) {
305                 $printsection = $hotpot->section;
306                 if ($course->format=='weeks' || $course->format=='topics') {
307                     // Show the zoom boxes
308                     if ($displaysection==$hotpot->section) {
309                         $strshowall = get_string('showall'.$course->format);
310                         $printsection .= '<br /><a href="index.php?id='.$course->id.'&section=all" title="'.$strshowall.'"><img src="'.$CFG->pixpath.'/i/all.gif" height=25 width=16 border=0 alt="'.$strshowall.'"></a><br />';
311                     } else {
312                         $strshowone = get_string('showonly'.preg_replace('|s$|', '', $course->format, 1), '', $hotpot->section);
313                         $printsection .=  '<br /><a href="index.php?id='.$course->id.'&section='.$hotpot->section.'" title="'.$strshowone.'"><img src="'.$CFG->pixpath.'/i/one.gif" class="icon" alt="'.$strshowone.'"></a><br />';
314                     }
315                 }
316             }
317             if ($currentsection>=0) {
318                 $table->data[] = 'hr';
319             }
320             $currentsection = $hotpot->section;
321         }
323         $class = ($hotpot->visible) ? '' : 'class="dimmed" ';
324         $quizname = '<a '.$class.'href="view.php?id='.$hotpot->coursemodule.'">'.$hotpot->name.'</A>';
325         $quizclose = empty($hotpot->timeclose) ? $strneverclosed : userdate($hotpot->timeclose);
327         // are there any totals for this hotpot?
328         if (empty($totals[$hotpot->id]->attemptcount)) {
329             $report = "&nbsp;";
330             $bestscore = "&nbsp;";
332         } else {
333           
334             $cm = get_coursemodule_from_instance('hotpot', $hotpot->id);
335             // report number of attempts and users
336             $report = get_string("viewallreports","quiz", $totals[$hotpot->id]->attemptcount);
337             if (has_capability('mod/hotpot:viewreport', get_context_instance(CONTEXT_MODULE, $cm->id))) {
338                 $report .= " (".$totals[$hotpot->id]->usercount." $strusers)";
339             }
340             $report = '<a href="report.php?hp='.$hotpot->id.'">'.$report.'</a>';
342             // get best score
343             if (is_numeric($totals[$hotpot->id]->maxscore)) {
344                                 $weighting = $hotpot->grade / 100;
345                                 $precision = hotpot_get_precision($hotpot);
346                                 $bestscore = round($totals[$hotpot->id]->maxscore * $weighting, $precision)." / $hotpot->grade";
347             } else {
348                 $bestscore = "&nbsp;";
349             }
350         }
352         if (has_capability('mod/hotpot:grade', $sitecontext)) {
353             if (in_array($hotpot->id, $regrade_hotpots)) {
354                 $report .= ' <font color="red">'.$strregraderequired.'</font>';
355             }
356         }
358         $data = array ();
360         if ($course->format=="weeks" || $course->format=="topics") {
361             array_push($data, $printsection);
362         }
364         if (has_capability('moodle/course:manageactivities', $coursecontext)) {
365             $updatebutton = ''
366             .   '<form '.$CFG->frametarget.'" method="get" action="'.$CFG->wwwroot.'/course/mod.php">'
367             .   '<input type="hidden" name="update" value="'.$hotpot->coursemodule.'" />'
368             .   $sesskey
369             .   '<input type="submit" value="'.$strupdate.'" />'
370             .   '</form>'
371             ;
372             array_push($data, $updatebutton);
373         }
375         array_push($data, $quizname, $quizclose, $bestscore, $report);
377         if (has_capability('mod/hotpot:grade', $sitecontext)) {
378             if (empty($totals[$hotpot->id]->detailcount)) {
379                 // no details records for this hotpot, so disable regrade
380                 $regradebutton = '&nbsp;';
381             } else {
382                 $strregradecheck = get_string('regradecheck', 'hotpot', strtr($hotpot->name, $quotes));
383                 $regradebutton = ''
384                 .   '<form target="_parent" method="post" action="'.$ME.'" onsubmit="var x=window.confirm('."'$strregradecheck'".');this.confirm.value=x;return x;">'
385                 .   '<input type="hidden" name="id" value="'.$course->id.'">'
386                 .   '<input type="hidden" name="regrade" value="'.$hotpot->id.'" />'
387                 .   '<input type="hidden" name="confirm" value="" />'
388                 .   $sesskey
389                 .   '<input type="submit" value="'.$strregrade.'" />'
390                 .   '</form>'
391                 ;
392             }
393             array_push($data, $regradebutton);
394         }
396         $table->data[] = $data;
397     }
399     echo "<br />";
401     print_table($table);
403     // Finish the page
404     print_footer($course);
405 ?>