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 '
'; - echo '
'; - echo '

'.get_string('displayoptions', 'quiz').': '; - echo ''; - echo ''; - echo ''; - echo ''; - echo ' '; - echo ' '; - echo ''; - echo '

'; - echo '
'; - 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 '
'; - echo '
'; - echo ''; - echo ''; + echo '
'; + echo ''; + echo ''; + echo ''; /// Print table - $table->print_html(); - + $table->print_html(); + /// Print "Select all" etc. - - echo ''; - echo '
'; - echo ''.get_string('selectall', 'quiz').' / '; - echo ''.get_string('selectnone', 'quiz').' '; - echo '  '; - $options = array('delete' => get_string('delete')); - echo choose_from_menu($options, 'action', '', get_string('withselected', 'quiz'), 'if(this.selectedIndex > 0) submitFormById(\'attemptsform\');', '', true); - echo ''; - echo ''; - echo '
'; + + echo ''; + echo '
'; + echo ''.get_string('selectall', 'quiz').' / '; + echo ''.get_string('selectnone', 'quiz').' '; + echo '  '; + $options = array('delete' => get_string('delete')); + echo choose_from_menu($options, 'action', '', get_string('withselected', 'quiz'), 'if(this.selectedIndex > 0) submitFormById(\'attemptsform\');', '', true); + echo ''; + echo ''; + echo '
'; /// Close form - echo '
'; + echo '
'; + /// Print display options + echo '
'; + echo '
'; + echo '

'.get_string('displayoptions', 'quiz').':

'; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo '
'; + echo '
'; + echo '
'; + echo ''; + 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 '\n"; + echo '\n"; + echo "\n"; + echo '
'; + $options["download"] = "Excel"; + print_single_button("report.php", $options, get_string("downloadexcel")); + echo "'; + $options["download"] = "CSV"; + print_single_button('report.php', $options, get_string("downloadtext")); + echo ""; + helpbutton("download", get_string("download","quiz"), "quiz"); + echo "
'; + } + elseif ($download == 'Excel') { + $workbook->close(); + } + elseif ($download == 'CSV') { + exit; + } + } else { - $table->print_html(); + if (!$download) { + $table->print_html(); + } } return true; }