diff --git a/lang/en/quiz.php b/lang/en/quiz.php
index dea8d09029c..cd87c6e6024 100644
--- a/lang/en/quiz.php
+++ b/lang/en/quiz.php
@@ -263,6 +263,7 @@ $string['numerical'] = 'Numerical';
$string['optional'] = 'optional';
$string['outof'] = ' out of a maximum of ';
$string['overdue'] = 'Overdue';
+$string['pagesize'] = 'Attempts shown per page: ';
$string['paragraphquestion'] = 'Paragraph Question not supported at line $a. The question will be ignored';
$string['parent'] = 'Parent';
$string['partiallycorrect'] = 'Partially correct';
diff --git a/mod/quiz/report/overview/report.php b/mod/quiz/report/overview/report.php
index cc0cc60e85b..fe302c496b5 100644
--- a/mod/quiz/report/overview/report.php
+++ b/mod/quiz/report/overview/report.php
@@ -15,8 +15,10 @@ class quiz_report extends quiz_default_report {
$strtimeformat = get_string('strftimedatetime');
$strreviewquestion = get_string('reviewresponse', 'quiz');
- /// Print header
- $this->print_header_and_tabs($cm, $course, $quiz, $reportmode="overview");
+ /// Only print headers if not asked to download data
+ if (!$download = optional_param('download', NULL)) {
+ $this->print_header_and_tabs($cm, $course, $quiz, $reportmode="overview");
+ }
/// Deal with actions
@@ -61,7 +63,17 @@ class quiz_report extends quiz_default_report {
/// Check to see if groups are being used in this quiz
if ($groupmode = groupmode($course, $cm)) { // Groups are being used
- $currentgroup = setup_and_print_groups($course, $groupmode, "report.php?id=$cm->id&mode=overview");
+ if (!$download) {
+ $currentgroup = setup_and_print_groups($course, $groupmode, "report.php?id=$cm->id&mode=overview");
+ } else {
+ if (isset($_GET['group'])) {
+ $changegroup = $_GET['group']; /// 0 or higher
+ } else {
+ $changegroup = -1; /// This means no group change was specified
+ }
+
+ $currentgroup = get_and_set_current_group($course, $groupmode, $changegroup);
+ }
} else {
$currentgroup = false;
}
@@ -97,7 +109,7 @@ class quiz_report extends quiz_default_report {
/// Set table options
if(!isset($SESSION->quiz_overview_table)) {
- $SESSION->quiz_overview_table = array('noattempts' => false, 'detailedmarks' => false);
+ $SESSION->quiz_overview_table = array('noattempts' => false, 'detailedmarks' => false, 'pagesize' => 10);
}
foreach($SESSION->quiz_overview_table as $option => $value) {
@@ -109,22 +121,13 @@ class quiz_report extends quiz_default_report {
$$option = $SESSION->quiz_overview_table[$option] = $urlparam;
}
}
-
- /// Print display options
-
- echo '
';
+
+ /// Now check if asked download of data
+ if ($download) {
+ $filename = clean_filename("$course->shortname ".format_string($quiz->name,true));
+ $sort = '';
+ $limit = '';
+ }
/// Define table columns
$tablecolumns = array('checkbox', 'picture', 'fullname', 'timestart', 'duration');
@@ -164,88 +167,170 @@ class quiz_report extends quiz_default_report {
}
}
- /// Set up the table
+ if (!$download) {
+ // Set up the table
- $table = new flexible_table('mod-quiz-report-overview-report');
+ $table = new flexible_table('mod-quiz-report-overview-report');
- $table->define_columns($tablecolumns);
- $table->define_headers($tableheaders);
- $table->define_baseurl($CFG->wwwroot.'/mod/quiz/report.php?mode=overview&id='.$cm->id);
+ $table->define_columns($tablecolumns);
+ $table->define_headers($tableheaders);
+ $table->define_baseurl($CFG->wwwroot.'/mod/quiz/report.php?mode=overview&id='.$cm->id);
- $table->sortable(true);
- $table->collapsible(true);
- $table->initialbars(count($users)>20);
+ $table->sortable(true);
+ $table->collapsible(true);
+ $table->initialbars(count($users)>20);
- $table->column_suppress('picture');
- $table->column_suppress('fullname');
+ $table->column_suppress('picture');
+ $table->column_suppress('fullname');
- $table->column_class('picture', 'picture');
+ $table->column_class('picture', 'picture');
- $table->set_attribute('cellspacing', '0');
- $table->set_attribute('id', 'attempts');
- $table->set_attribute('class', 'generaltable generalbox');
+ $table->set_attribute('cellspacing', '0');
+ $table->set_attribute('id', 'attempts');
+ $table->set_attribute('class', 'generaltable generalbox');
- // Start working -- this is necessary as soon as the niceties are over
- $table->setup();
+ // Start working -- this is necessary as soon as the niceties are over
+ $table->setup();
+ } elseif ($download =='Excel') {
+ require_once("$CFG->libdir/excel/Worksheet.php");
+ require_once("$CFG->libdir/excel/Workbook.php");
+
+ $filename .= ".xls";
+ header("Content-Type: application/vnd.ms-excel");
+ header("Content-Disposition: attachment; filename=\"$filename\"");
+ header("Expires: 0");
+ header("Cache-Control: must-revalidate,post-check=0,pre-check=0");
+ header("Pragma: public");
+ header("Content-Transfer-Encoding: binary");
+
+ $workbook = new Workbook("-");
+ // Creating the first worksheet
+ $sheettitle = get_string('reportresponses','quiz_responses');
+ $myxls =& $workbook->add_worksheet($sheettitle);
+ /// format types
+ $format =& $workbook->add_format();
+ $format->set_bold(0);
+ $formatbc =& $workbook->add_format();
+ $formatbc->set_bold(1);
+ $formatbc->set_align('center');
+ $formatb =& $workbook->add_format();
+ $formatb->set_bold(1);
+ $formaty =& $workbook->add_format();
+ $formaty->set_bg_color('yellow');
+ $formatc =& $workbook->add_format();
+ $formatc->set_align('center');
+ $formatr =& $workbook->add_format();
+ $formatr->set_bold(1);
+ $formatr->set_color('red');
+ $formatr->set_align('center');
+ $formatg =& $workbook->add_format();
+ $formatg->set_bold(1);
+ $formatg->set_color('green');
+ $formatg->set_align('center');
+ // Here starts workshhet headers
+
+ $headers = array(get_string('fullname'), get_string('startedon', 'quiz'), get_string('attemptduration', 'quiz'));
+
+ if ($quiz->grade) {
+ $headers[] = get_string('grade', 'quiz').'/'.$quiz->grade;
+ }
+ if($detailedmarks) {
+ foreach ($questions as $question) {
+ $headers[] = '#'.$question->number;
+ }
+ }
+ $colnum = 0;
+ foreach ($headers as $item) {
+ $myxls->write(0,$colnum,$item,$formatbc);
+ $colnum++;
+ }
+ $rownum=1;
+ } elseif ($download=='CSV') {
+ $filename .= ".txt";
+
+ header("Content-Type: application/download\n");
+ header("Content-Disposition: attachment; filename=\"$filename\"");
+ header("Expires: 0");
+ header("Cache-Control: must-revalidate,post-check=0,pre-check=0");
+ header("Pragma: public");
+
+ $headers = get_string('fullname')."\t".get_string('startedon', 'quiz')."\t".get_string('attemptduration', 'quiz');
+
+ if ($quiz->grade) {
+ $headers .= "\t".get_string('grade', 'quiz')."/".$quiz->grade;
+ }
+ if($detailedmarks) {
+ foreach ($questions as $question) {
+ $headers .= "\t#".$question->number;
+ }
+ }
+ echo $headers." \n";
+ }
+
+
// Construct the SQL
$select = 'SELECT '.$db->Concat('u.id', '\'#\'', $db->IfNull('qa.attempt', '0')).' AS uniqueid, qa.id AS attempt, qa.uniqueid as attemptuniqueid, u.id AS userid, u.firstname, u.lastname, u.picture, '.
'qa.sumgrades, qa.timefinish, qa.timestart, qa.timefinish - qa.timestart AS duration ';
$from = 'FROM '.$CFG->prefix.'user u LEFT JOIN '.$CFG->prefix.'quiz_attempts qa ON (u.id = qa.userid AND qa.quiz = '.$quiz->id.') ';
- $where = 'WHERE u.id IN ('.implode(',', $users).') ';
+ $where = 'WHERE u.id IN ('.implode(',', $users).') ';
// Add extra limits if we 're not interested in students without attempts
if(!$noattempts) {
$where .= 'AND '.$db->IfNull('qa.attempt', '0').' != 0 ';
}
-
- // Add extra limits due to initials bar
- if($table->get_sql_where()) {
- $where .= 'AND '.$table->get_sql_where();
- }
-
- // Count the records NOW, before funky question grade sorting messes up $from
- $total = count_records_sql('SELECT COUNT(DISTINCT('.$db->Concat('u.id', '\'#\'', $db->IfNull('qa.attempt', '0')).')) '.$from.$where);
-
- // Add extra limits due to sorting by question grade
- if($sort = $table->get_sql_sort()) {
- $sortparts = explode(',', $sort);
- $newsort = array();
- $questionsort = false;
- foreach($sortparts as $sortpart) {
- $sortpart = trim($sortpart);
- if(substr($sortpart, 0, 1) == '$') {
- if(!$questionsort) {
- $qid = intval(substr($sortpart, 1));
- $select .= ', grade ';
- $from .= 'LEFT JOIN '.$CFG->prefix.'quiz_newest_states qns ON qns.attemptid = qa.attemptuniqueid '.
- 'LEFT JOIN '.$CFG->prefix.'quiz_states qs ON qs.id = qns.newgraded ';
- $where .= ' AND ('.sql_isnull('qns.questionid').' OR qns.questionid = '.$qid.')';
- $newsort[] = 'grade '.(strpos($sortpart, 'ASC')? 'ASC' : 'DESC');
- $questionsort = true;
- }
- }
- else {
- $newsort[] = $sortpart;
- }
+ if (!$download) {
+ // Add extra limits due to initials bar
+ if($table->get_sql_where()) {
+ $where .= 'AND '.$table->get_sql_where();
}
- // Reconstruct the sort string
- $sort = ' ORDER BY '.implode(', ', $newsort);
- }
+ // Count the records NOW, before funky question grade sorting messes up $from
+ $total = count_records_sql('SELECT COUNT(DISTINCT('.$db->Concat('u.id', '\'#\'', $db->IfNull('qa.attempt', '0')).')) '.$from.$where);
- $table->pagesize(10, $total);
+ // Add extra limits due to sorting by question grade
+ if($sort = $table->get_sql_sort()) {
+ $sortparts = explode(',', $sort);
+ $newsort = array();
+ $questionsort = false;
+ foreach($sortparts as $sortpart) {
+ $sortpart = trim($sortpart);
+ if(substr($sortpart, 0, 1) == '$') {
+ if(!$questionsort) {
+ $qid = intval(substr($sortpart, 1));
+ $select .= ', grade ';
+ $from .= 'LEFT JOIN '.$CFG->prefix.'quiz_newest_states qns ON qns.attemptid = qa.attemptuniqueid '.
+ 'LEFT JOIN '.$CFG->prefix.'quiz_states qs ON qs.id = qns.newgraded ';
+ $where .= ' AND ('.sql_isnull('qns.questionid').' OR qns.questionid = '.$qid.')';
+ $newsort[] = 'grade '.(strpos($sortpart, 'ASC')? 'ASC' : 'DESC');
+ $questionsort = true;
+ }
+ }
+ else {
+ $newsort[] = $sortpart;
+ }
+ }
- if($table->get_page_start() !== '' && $table->get_page_size() !== '') {
- $limit = ' '.sql_paging_limit($table->get_page_start(), $table->get_page_size());
- }
- else {
- $limit = '';
- }
+ // Reconstruct the sort string
+ $sort = ' ORDER BY '.implode(', ', $newsort);
+ }
+ // Now it is time to page the data
+ if (!isset($pagesize)) {
+ $pagesize = 10;
+ }
+ $table->pagesize($pagesize, $total);
+
+ if($table->get_page_start() !== '' && $table->get_page_size() !== '') {
+ $limit = ' '.sql_paging_limit($table->get_page_start(), $table->get_page_size());
+ }
+ else {
+ $limit = '';
+ }
+ }
+
/// Fetch the attempts
-
$attempts = get_records_sql($select.$from.$where.$sort.$limit);
/// Build table rows
@@ -262,21 +347,34 @@ class quiz_report extends quiz_default_report {
else {
$userlink = ''.fullname($attempt).'';
}
-
- $row = array(
- '',
- $picture,
- $userlink,
- empty($attempt->attempt) ? '-' : ''.userdate($attempt->timestart, $strtimeformat).'',
- empty($attempt->attempt) ? '-' :
- (empty($attempt->timefinish) ? get_string('unfinished', 'quiz') :
- format_time($attempt->duration))
- );
-
- if ($quiz->grade) {
- $row[] = $attempt->sumgrades === NULL ? '-' : ''.round($attempt->sumgrades / $quiz->sumgrades * $quiz->grade,$quiz->decimalpoints).'';
+ if (!$download) {
+ $row = array(
+ '',
+ $picture,
+ $userlink,
+ empty($attempt->attempt) ? '-' : ''.userdate($attempt->timestart, $strtimeformat).'',
+ empty($attempt->attempt) ? '-' :
+ (empty($attempt->timefinish) ? get_string('unfinished', 'quiz') :
+ format_time($attempt->duration))
+ );
+ }
+ else {
+ $row = array(fullname($attempt),
+ empty($attempt->attempt) ? '-' : userdate($attempt->timestart, $strtimeformat),
+ empty($attempt->attempt) ? '-' :
+ (empty($attempt->timefinish) ? get_string('unfinished', 'quiz') :
+ format_time($attempt->duration))
+ );
}
+ if ($quiz->grade) {
+ if (!$download) {
+ $row[] = $attempt->sumgrades === NULL ? '-' : ''.round($attempt->sumgrades / $quiz->sumgrades * $quiz->grade,$quiz->decimalpoints).'';
+ }
+ else {
+ $row[] = $attempt->sumgrades === NULL ? '-' : round($attempt->sumgrades / $quiz->sumgrades * $quiz->grade,$quiz->decimalpoints);
+ }
+ }
if($detailedmarks) {
if(empty($attempt->attempt)) {
foreach($questionids as $questionid) {
@@ -291,44 +389,118 @@ class quiz_report extends quiz_default_report {
// This is an old-style attempt
$grade = round(get_field('quiz_states', 'grade', 'attempt', $attempt->attempt, 'question', $questionid), $quiz->decimalpoints);
}
- $row[] = link_to_popup_window ('/mod/quiz/reviewquestion.php?state='.$gradedstateid.'&number='.$questions[$questionid]->number, 'reviewquestion', $grade, 450, 650, $strreviewquestion, 'none', true);
+ if (!$download) {
+ $row[] = link_to_popup_window ('/mod/quiz/reviewquestion.php?state='.$gradedstateid.'&number='.$questions[$questionid]->number, 'reviewquestion', $grade, 450, 650, $strreviewquestion, 'none', true);
+ }
+ else {
+ $row[] = $grade;
+ }
}
}
}
-
- $table->add_data($row);
+ if (!$download) {
+ $table->add_data($row);
+ }
+ elseif ($download == 'Excel') {
+ $colnum = 0;
+ foreach($row as $item){
+ $myxls->write($rownum,$colnum,$item,$format);
+ $colnum++;
+ }
+ $rownum++;
+ }
+ elseif ($download=='CSV') {
+ $text = implode("\t", $row);
+ echo $text." \n";
+ }
}
-
+ if (!$download) {
/// Start form
- echo '';
+ /// Print display options
+ echo '';
+ echo '
';
+ echo '
';
+ echo "\n";
+
+ echo '';
+ unset($options);
+ $options["id"] = "$cm->id";
+ $options["q"] = "$quiz->id";
+ $options["mode"] = "overview";
+ $options['sesskey'] = sesskey();
+ $options["noheader"] = "yes";
+ echo '| ';
+ $options["download"] = "Excel";
+ print_single_button("report.php", $options, get_string("downloadexcel"));
+ echo " | \n";
+ echo '';
+ $options["download"] = "CSV";
+ print_single_button('report.php', $options, get_string("downloadtext"));
+ echo " | \n";
+ echo "";
+ helpbutton("download", get_string("download","quiz"), "quiz");
+ echo " | \n";
+ echo '
';
+ }
+ elseif ($download == 'Excel') {
+ $workbook->close();
+ }
+ elseif ($download == 'CSV') {
+ exit;
+ }
+
}
else {
- $table->print_html();
+ if (!$download) {
+ $table->print_html();
+ }
}
return true;
}