Exemplo n.º 1
0
 /**
  * (non-PHPdoc)
  *
  * @see offlinequiz_default_report::display()
  */
 public function display($offlinequiz, $cm, $course)
 {
     global $CFG, $OUTPUT, $SESSION, $DB;
     // Define some strings.
     $strtimeformat = get_string('strftimedatetime');
     $letterstr = ' ABCDEFGHIJKLMNOPQRSTUVWXYZ';
     offlinequiz_load_useridentification();
     $offlinequizconfig = get_config('offlinequiz');
     // Deal with actions.
     $action = optional_param('action', '', PARAM_ACTION);
     // Only print headers if not asked to download data or delete data.
     if (!($download = optional_param('download', null, PARAM_TEXT)) && !$action == 'delete') {
         $this->print_header_and_tabs($cm, $course, $offlinequiz, 'overview');
         echo $OUTPUT->box_start('linkbox');
         echo $OUTPUT->heading(format_string($offlinequiz->name));
         echo $OUTPUT->heading(get_string('results', 'offlinequiz'));
         require_once $CFG->libdir . '/grouplib.php';
         echo groups_print_activity_menu($cm, $CFG->wwwroot . '/mod/offlinequiz/report.php?id=' . $cm->id . '&mode=overview', true);
         echo $OUTPUT->box_end();
         echo '<br/>';
     }
     $context = context_module::instance($cm->id);
     $systemcontext = context_system::instance();
     // Set table options.
     $noresults = optional_param('noresults', 0, PARAM_INT);
     $pagesize = optional_param('pagesize', 10, PARAM_INT);
     $groupid = optional_param('group', 0, PARAM_INT);
     if ($pagesize < 1) {
         $pagesize = 10;
     }
     $answerletters = 'abcdefghijklmnopqrstuvwxyz';
     if ($action == 'delete' && confirm_sesskey()) {
         $selectedresultids = array();
         $params = (array) data_submitted();
         foreach ($params as $key => $value) {
             if (preg_match('!^s([0-9]+)$!', $key, $matches)) {
                 $selectedresultids[] = $matches[1];
             }
         }
         if ($selectedresultids) {
             foreach ($selectedresultids as $resultid) {
                 if ($resultid && ($todelete = $DB->get_record('offlinequiz_results', array('id' => $resultid)))) {
                     offlinequiz_delete_result($resultid, $context);
                     // Log this event.
                     $params = array('objectid' => $resultid, 'relateduserid' => $todelete->userid, 'context' => context_module::instance($cm->id), 'other' => array('mode' => 'overview'));
                     $event = \mod_offlinequiz\event\attempt_deleted::create($params);
                     $event->trigger();
                     // Change the status of all related pages with error 'resultexists' to 'suspended'.
                     $user = $DB->get_record('user', array('id' => $todelete->userid));
                     $group = $DB->get_record('offlinequiz_groups', array('id' => $todelete->offlinegroupid));
                     $sql = "SELECT id\n                                  FROM {offlinequiz_scanned_pages}\n                                 WHERE offlinequizid = :offlinequizid\n                                   AND userkey = :userkey\n                                   AND groupnumber = :groupnumber\n                                   AND status = 'error'\n                                   AND (error = 'resultexists' OR error = 'differentresultexists')";
                     $params = array('offlinequizid' => $offlinequiz->id, 'userkey' => $user->{$offlinequizconfig->ID_field}, 'groupnumber' => $group->number);
                     $otherpages = $DB->get_records_sql($sql, $params);
                     foreach ($otherpages as $page) {
                         $DB->set_field('offlinequiz_scanned_pages', 'status', 'suspended', array('id' => $page->id));
                         $DB->set_field('offlinequiz_scanned_pages', 'error', '', array('id' => $page->id));
                     }
                 }
             }
             offlinequiz_grade_item_update($offlinequiz, 'reset');
             offlinequiz_update_grades($offlinequiz);
             redirect(new moodle_url('/mod/offlinequiz/report.php', array('mode' => 'overview', 'id' => $cm->id, 'noresults' => $noresults, 'pagesize' => $pagesize)));
         }
     }
     // Now check if asked download of data.
     if ($download) {
         $filename = clean_filename("{$course->shortname} " . format_string($offlinequiz->name, true));
         $sort = '';
     }
     // Fetch the group data.
     $groups = $DB->get_records('offlinequiz_groups', array('offlinequizid' => $offlinequiz->id), 'number', '*', 0, $offlinequiz->numgroups);
     // Define table columns.
     $tablecolumns = array('checkbox', 'picture', 'fullname', $offlinequizconfig->ID_field, 'timestart', 'offlinegroupid', 'sumgrades');
     $tableheaders = array('<input type="checkbox" name="toggle" onClick="if (this.checked) {select_all_in(\'DIV\',null,\'tablecontainer\');}
             else {deselect_all_in(\'DIV\',null,\'tablecontainer\');}"/>', '', get_string('fullname'), get_string($offlinequizconfig->ID_field), get_string('importedon', 'offlinequiz'), get_string('group'), get_string('grade', 'offlinequiz'));
     $checked = array();
     // Get participants list.
     $withparticipants = false;
     if ($lists = $DB->get_records('offlinequiz_p_lists', array('offlinequizid' => $offlinequiz->id))) {
         $withparticipants = true;
         $tablecolumns[] = 'checked';
         $tableheaders[] = get_string('present', 'offlinequiz');
         foreach ($lists as $list) {
             $participants = $DB->get_records('offlinequiz_participants', array('listid' => $list->id));
             foreach ($participants as $participant) {
                 $checked[$participant->userid] = $participant->checked;
             }
         }
     }
     if (!$download) {
         // Set up the table.
         $params = array('offlinequiz' => $offlinequiz, 'noresults' => $noresults, 'pagesize' => $pagesize);
         $table = new offlinequiz_results_table('mod-offlinequiz-report-overview-report', $params);
         $table->define_columns($tablecolumns);
         $table->define_headers($tableheaders);
         $table->define_baseurl($CFG->wwwroot . '/mod/offlinequiz/report.php?mode=overview&amp;id=' . $cm->id . '&amp;noresults=' . $noresults . '&amp;pagesize=' . $pagesize);
         $table->sortable(true);
         $table->no_sorting('checkbox');
         if ($withparticipants) {
             $table->no_sorting('checked');
         }
         $table->column_suppress('picture');
         $table->column_suppress('fullname');
         $table->column_class('picture', 'picture');
         $table->column_class($offlinequizconfig->ID_field, 'userkey');
         $table->column_class('timestart', 'timestart');
         $table->column_class('offlinegroupid', 'offlinegroupid');
         $table->column_class('sumgrades', 'sumgrades');
         $table->set_attribute('cellpadding', '2');
         $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();
     } else {
         if ($download == 'ODS') {
             require_once "{$CFG->libdir}/odslib.class.php";
             $filename .= ".ods";
             // Creating a workbook.
             $workbook = new MoodleODSWorkbook("-");
             // Sending HTTP headers.
             $workbook->send($filename);
             // Creating the first worksheet.
             $sheettitle = get_string('reportoverview', 'offlinequiz');
             $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($offlinequizconfig->ID_field), get_string('firstname'), get_string('lastname'), get_string('importedon', 'offlinequiz'), get_string('group'), get_string('grade', 'offlinequiz'));
             if (!empty($withparticipants)) {
                 $headers[] = get_string('present', 'offlinequiz');
             }
             $colnum = 0;
             foreach ($headers as $item) {
                 $myxls->write(0, $colnum, $item, $formatbc);
                 $colnum++;
             }
             $rownum = 1;
         } else {
             if ($download == 'Excel') {
                 require_once "{$CFG->libdir}/excellib.class.php";
                 $filename .= ".xls";
                 // Creating a workbook.
                 $workbook = new MoodleExcelWorkbook("-");
                 // Sending HTTP headers.
                 $workbook->send($filename);
                 // Creating the first worksheet.
                 $sheettitle = get_string('results', 'offlinequiz');
                 $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 worksheet headers.
                 $headers = array(get_string($offlinequizconfig->ID_field), get_string('firstname'), get_string('lastname'), get_string('importedon', 'offlinequiz'), get_string('group'), get_string('grade', 'offlinequiz'));
                 if (!empty($withparticipants)) {
                     $headers[] = get_string('present', 'offlinequiz');
                 }
                 $colnum = 0;
                 foreach ($headers as $item) {
                     $myxls->write(0, $colnum, $item, $formatbc);
                     $colnum++;
                 }
                 $rownum = 1;
             } else {
                 if ($download == 'CSV') {
                     $filename .= ".csv";
                     header("Content-Encoding: UTF-8");
                     header("Content-Type: text/csv; charset=utf-8");
                     header("Content-Disposition: attachment; filename=\"{$filename}\"");
                     header("Expires: 0");
                     header("Cache-Control: must-revalidate,post-check=0,pre-check=0");
                     header("Pragma: public");
                     echo "";
                     // UTF-8 BOM.
                     $headers = get_string($offlinequizconfig->ID_field) . ", " . get_string('fullname') . ", " . get_string('importedon', 'offlinequiz') . ", " . get_string('group') . ", " . get_string('grade', 'offlinequiz');
                     if (!empty($withparticipants)) {
                         $headers .= ", " . get_string('present', 'offlinequiz');
                     }
                     echo $headers . " \n";
                 } else {
                     if ($download == 'CSVplus1' || $download == 'CSVpluspoints') {
                         $filename .= ".csv";
                         header("Content-Encoding: UTF-8");
                         header("Content-Type: text/csv; charset=utf-8");
                         header("Content-Disposition: attachment; filename=\"{$filename}\"");
                         header("Expires: 0");
                         header("Cache-Control: must-revalidate,post-check=0,pre-check=0");
                         header("Pragma: public");
                         echo "";
                         // UTF-8 BOM.
                         // Print the table headers.
                         echo get_string('firstname') . ',' . get_string('lastname') . ',' . get_string($offlinequizconfig->ID_field) . ',' . get_string('group');
                         $maxquestions = offlinequiz_get_maxquestions($offlinequiz, $groups);
                         for ($i = 0; $i < $maxquestions; $i++) {
                             echo ', ' . get_string('question') . ' ' . ($i + 1);
                         }
                         echo "\n";
                         // Print the correct answer bit-strings.
                         foreach ($groups as $group) {
                             if ($group->templateusageid) {
                                 $quba = question_engine::load_questions_usage_by_activity($group->templateusageid);
                                 $slots = $quba->get_slots();
                                 echo ', ,' . get_string('correct', 'offlinequiz');
                                 echo ',' . $group->number;
                                 foreach ($slots as $slot) {
                                     $slotquestion = $quba->get_question($slot);
                                     $qtype = $slotquestion->get_type_name();
                                     if ($qtype == 'multichoice' || $qtype == 'multichoiceset') {
                                         $attempt = $quba->get_question_attempt($slot);
                                         $order = $slotquestion->get_order($attempt);
                                         // Order of the answers.
                                         $tempstr = ",";
                                         $letters = array();
                                         $counter = 0;
                                         foreach ($order as $key => $answerid) {
                                             $fraction = $DB->get_field('question_answers', 'fraction', array('id' => $answerid));
                                             if ($fraction > 0) {
                                                 $letters[] = $answerletters[$counter];
                                             }
                                             $counter++;
                                         }
                                         if (empty($letters)) {
                                             $tempstr .= '99';
                                         } else {
                                             $tempstr .= implode('/', $letters);
                                         }
                                         echo $tempstr;
                                     }
                                 }
                                 echo "\n";
                             }
                         }
                     }
                 }
             }
         }
     }
     $coursecontext = context_course::instance($course->id);
     $contextids = $coursecontext->get_parent_context_ids(true);
     // Construct the SQL
     // First get roleids for students from leagcy.
     if (!($roles = get_roles_with_capability('mod/offlinequiz:attempt', CAP_ALLOW, $systemcontext))) {
         error("No roles with capability 'moodle/offlinequiz:attempt' defined in system context");
     }
     $roleids = array();
     foreach ($roles as $role) {
         $roleids[] = $role->id;
     }
     $rolelist = implode(',', $roleids);
     $select = "SELECT " . $DB->sql_concat('u.id', "'#'", "COALESCE(qa.usageid, 0)") . " AS uniqueid,\n        qa.id AS resultid, u.id, qa.usageid, qa.offlinegroupid, qa.status,\n        u.id AS userid, u.firstname, u.lastname,\n        u.alternatename, u.middlename, u.firstnamephonetic, u.lastnamephonetic,\n        u.picture, u." . $offlinequizconfig->ID_field . ",\n        qa.sumgrades, qa.timefinish, qa.timestart, qa.timefinish - qa.timestart AS duration ";
     $result = $DB->get_in_or_equal($contextids, SQL_PARAMS_NAMED, 'ctx');
     list($contexttest, $cparams) = $result;
     list($roletest, $rparams) = $DB->get_in_or_equal($roleids, SQL_PARAMS_NAMED, 'role');
     $from = "FROM {user} u\n                  JOIN {role_assignments} ra ON ra.userid = u.id\n             LEFT JOIN {offlinequiz_results} qa ON u.id = qa.userid AND qa.offlinequizid = :offlinequizid\n             ";
     $where = " WHERE ra.contextid {$contexttest} AND ra.roleid {$roletest} ";
     $params = array('offlinequizid' => $offlinequiz->id);
     $params = array_merge($params, $cparams, $rparams);
     if ($groupid) {
         $from .= " JOIN {groups_members} gm ON gm.userid = u.id ";
         $where .= " AND gm.groupid = :groupid ";
         $params['groupid'] = $groupid;
     }
     if (empty($noresults)) {
         $where = $where . " AND qa.userid IS NOT NULL\n                                AND qa.status = 'complete'";
         // Show ONLY students with results.
     } else {
         if ($noresults == 1) {
             // The value noresults = 1 means only no results, so make the left join ask for only records
             // where the right is null (no results).
             $where .= ' AND qa.userid IS NULL';
             // Show ONLY students without results.
         } else {
             if ($noresults == 3) {
                 // We want all results, also the partial ones.
                 $from = "FROM {user} u\n                      JOIN {offlinequiz_results} qa ON u.id = qa.userid ";
                 $where = " WHERE qa.offlinequizid = :offlinequizid";
             }
         }
     }
     // The value noresults = 2 means we want all students, with or without results.
     $countsql = 'SELECT COUNT(DISTINCT(u.id)) ' . $from . $where;
     if (!$download) {
         // Count the records NOW, before funky question grade sorting messes up $from.
         $totalinitials = $DB->count_records_sql($countsql, $params);
         // Add extra limits due to initials bar.
         list($ttest, $tparams) = $table->get_sql_where();
         if (!empty($ttest)) {
             $where .= ' AND ' . $ttest;
             $countsql .= ' AND ' . $ttest;
             $params = array_merge($params, $tparams);
         }
         $total = $DB->count_records_sql($countsql, $params);
         // Add extra limits due to sorting by question grade.
         $sort = $table->get_sql_sort();
         // Fix some wired sorting.
         if (empty($sort)) {
             $sort = ' ORDER BY u.lastname';
         } else {
             $sort = ' ORDER BY ' . $sort;
         }
         $table->pagesize($pagesize, $total);
     }
     // Fetch the results.
     if (!$download) {
         $results = $DB->get_records_sql($select . $from . $where . $sort, $params, $table->get_page_start(), $table->get_page_size());
     } else {
         $results = $DB->get_records_sql($select . $from . $where . $sort, $params);
     }
     // Build table rows.
     if (!$download) {
         $table->initialbars(true);
     }
     if (!empty($results) || !empty($noresults)) {
         foreach ($results as $result) {
             $user = $DB->get_record('user', array('id' => $result->userid));
             $picture = $OUTPUT->user_picture($user, array('courseid' => $course->id));
             if (!empty($result->resultid)) {
                 $checkbox = '<input type="checkbox" name="s' . $result->resultid . '" value="' . $result->resultid . '" />';
             } else {
                 $checkbox = '';
             }
             if (!empty($result) && (empty($result->resultid) || $result->timefinish == 0)) {
                 $resultdate = '-';
             } else {
                 $resultdate = userdate($result->timefinish, $strtimeformat);
             }
             if (!empty($result) && $result->offlinegroupid) {
                 $groupletter = $letterstr[$groups[$result->offlinegroupid]->number];
             } else {
                 $groupletter = '-';
             }
             $userlink = '<a href="' . $CFG->wwwroot . '/user/view.php?id=' . $result->userid . '&amp;course=' . $course->id . '">' . fullname($result) . '</a>';
             if (!$download) {
                 $row = array($checkbox, $picture, $userlink, $result->{$offlinequizconfig->ID_field}, $resultdate, $groupletter);
             } else {
                 $row = array($result->{$offlinequizconfig->ID_field}, $result->firstname, $result->lastname, $resultdate, $groupletter);
             }
             if (!empty($result) && $result->offlinegroupid) {
                 $outputgrade = format_float($result->sumgrades / $groups[$result->offlinegroupid]->sumgrades * $offlinequiz->grade, $offlinequiz->decimalpoints);
             } else {
                 $outputgrade = '-';
             }
             if (!$download) {
                 if ($result->status == 'partial') {
                     $row[] = get_string('partial', 'offlinequiz');
                 } else {
                     if ($result->sumgrades === null) {
                         $row[] = '-';
                     } else {
                         $row[] = '<a href="review.php?q=' . $offlinequiz->id . '&amp;resultid=' . $result->resultid . '">' . $outputgrade . '</a>';
                     }
                 }
                 if ($withparticipants) {
                     $row[] = !empty($checked[$result->userid]) ? "<img src=\"{$CFG->wwwroot}/mod/offlinequiz/pix/tick.gif\" alt=\"" . get_string('ischecked', 'offlinequiz') . "\">" : "<img src=\"{$CFG->wwwroot}/mod/offlinequiz/pix/cross.gif\" alt=\"" . get_string('isnotchecked', 'offlinequiz') . "\">";
                 }
             } else {
                 if ($download != 'CSVplus1' || $download == 'CSVpluspoints') {
                     $row[] = $result->sumgrades === null ? '-' : $outputgrade;
                     if ($withparticipants) {
                         if (array_key_exists($result->userid, $checked)) {
                             $row[] = $checked[$result->userid] ? get_string('ok') : '-';
                         } else {
                             $row[] = '-';
                         }
                     }
                 }
             }
             if (!$download) {
                 $table->add_data($row);
             } else {
                 if ($download == 'Excel' or $download == 'ODS') {
                     $colnum = 0;
                     foreach ($row as $item) {
                         $myxls->write($rownum, $colnum, $item, $format);
                         $colnum++;
                     }
                     $rownum++;
                 } else {
                     if ($download == 'CSV') {
                         $text = implode(',', $row);
                         echo $text . "\n";
                     } else {
                         if ($download == 'CSVplus1' || $download == 'CSVpluspoints') {
                             $text = $row[1] . ',' . $row[2] . ',' . $row[0] . ',' . $groups[$result->offlinegroupid]->number;
                             if ($pages = $DB->get_records('offlinequiz_scanned_pages', array('resultid' => $result->resultid), 'pagenumber ASC')) {
                                 foreach ($pages as $page) {
                                     if ($page->status == 'ok' || $page->status == 'submitted') {
                                         $choices = $DB->get_records('offlinequiz_choices', array('scannedpageid' => $page->id), 'slotnumber, choicenumber');
                                         $counter = 0;
                                         $oldslot = -1;
                                         $letters = array();
                                         foreach ($choices as $choice) {
                                             if ($oldslot == -1) {
                                                 $oldslot = $choice->slotnumber;
                                             } else {
                                                 if ($oldslot != $choice->slotnumber) {
                                                     if (empty($letters)) {
                                                         $text .= ',99';
                                                     } else {
                                                         $text .= ',' . implode('/', $letters);
                                                     }
                                                     $counter = 0;
                                                     $oldslot = $choice->slotnumber;
                                                     $letters = array();
                                                 }
                                             }
                                             if ($choice->value == 1) {
                                                 $letters[] = $answerletters[$counter];
                                             }
                                             $counter++;
                                         }
                                         if (empty($letters)) {
                                             $text .= ',99';
                                         } else {
                                             $text .= ',' . implode('/', $letters);
                                         }
                                     }
                                 }
                             }
                             echo $text . "\n";
                             if ($download == 'CSVpluspoints') {
                                 $text = $row[1] . ',' . $row[2] . ',' . $row[0] . ',' . $groups[$result->offlinegroupid]->number;
                                 $quba = question_engine::load_questions_usage_by_activity($result->usageid);
                                 $slots = $quba->get_slots();
                                 foreach ($slots as $slot) {
                                     $slotquestion = $quba->get_question($slot);
                                     $attempt = $quba->get_question_attempt($slot);
                                     $text .= ',' . format_float($attempt->get_mark(), $offlinequiz->decimalpoints, false);
                                 }
                                 echo $text . "\n";
                             }
                         }
                     }
                 }
             }
         }
         // End foreach ($results...
     } else {
         if (!$download) {
             $table->print_initials_bar();
         }
     }
     if (!$download) {
         // Print table.
         $table->finish_html();
         if (!empty($results)) {
             echo '<form id="downloadoptions" action="report.php" method="get">';
             echo ' <input type="hidden" name="id" value="' . $cm->id . '" />';
             echo ' <input type="hidden" name="q" value="' . $offlinequiz->id . '" />';
             echo ' <input type="hidden" name="mode" value="overview" />';
             echo ' <input type="hidden" name="noheader" value="yes" />';
             echo ' <table class="boxaligncenter"><tr><td>';
             $options = array('Excel' => get_string('excelformat', 'offlinequiz'), 'ODS' => get_string('odsformat', 'offlinequiz'), 'CSV' => get_string('csvformat', 'offlinequiz'), 'CSVplus1' => get_string('csvplus1format', 'offlinequiz'), 'CSVpluspoints' => get_string('csvpluspointsformat', 'offlinequiz'));
             print_string('downloadresultsas', 'offlinequiz');
             echo "</td><td>";
             echo html_writer::select($options, 'download', '', false);
             echo ' <input type="submit" value="' . get_string('download') . '" />';
             echo ' <script type="text/javascript">' . "\n<!--\n" . 'document.getElementById("noscriptmenuaction").style.display = "none";' . "\n-->\n" . '</script>';
             echo " </td>\n";
             echo "<td>";
             echo "</td>\n";
             echo '</tr></table></form>';
         }
     } else {
         if ($download == 'Excel' || $download == 'ODS') {
             $workbook->close();
             exit;
         } else {
             if ($download == 'CSV' || $download == 'CSVplus1' || $download == 'CSVpluspoints') {
                 exit;
             }
         }
     }
     // Print display options.
     echo '<div class="controls">';
     echo '<form id="options" action="report.php" method="get">';
     echo '<div class=centerbox>';
     echo '<p>' . get_string('displayoptions', 'offlinequiz') . ': </p>';
     echo '<input type="hidden" name="id" value="' . $cm->id . '" />';
     echo '<input type="hidden" name="q" value="' . $offlinequiz->id . '" />';
     echo '<input type="hidden" name="mode" value="overview" />';
     echo '<input type="hidden" name="detailedmarks" value="0" />';
     echo '<table id="overview-options" class="boxaligncenter">';
     echo '<tr align="left">';
     echo '<td><label for="pagesize">' . get_string('pagesizeparts', 'offlinequiz') . '</label></td>';
     echo '<td><input type="text" id="pagesize" name="pagesize" size="3" value="' . $pagesize . '" /></td>';
     echo '</tr>';
     echo '<tr align="left">';
     echo '<td colspan="2">';
     $options = array();
     $options[] = get_string('attemptsonly', 'offlinequiz');
     $options[] = get_string('noattemptsonly', 'offlinequiz');
     $options[] = get_string('allstudents', 'offlinequiz');
     $options[] = get_string('allresults', 'offlinequiz');
     echo html_writer::select($options, 'noresults', $noresults, '');
     echo '</td></tr>';
     echo '<tr><td colspan="2" align="center">';
     echo '<input type="submit" value="' . get_string('go') . '" />';
     echo '</td></tr></table>';
     echo '</div>';
     echo '</form>';
     echo '</div>';
     echo "\n";
     return true;
 }
        print_error("The course module for the offlinequiz with id {$q} is missing");
    }
}
$offlinequiz->optionflags = 0;
require_login($course->id, false, $cm);
if (!($context = context_module::instance($cm->id))) {
    print_error("The context for the course module with ID {$cm->id} is missing");
}
$offlinequiz->cmid = $cm->id;
$coursecontext = context_course::instance($course->id);
// We redirect students to info.
if (!has_capability('mod/offlinequiz:createofflinequiz', $context)) {
    redirect('view.php?q=' . $offlinequiz->id);
}
// If not in all group questions have been set up yet redirect to edit.php.
offlinequiz_load_useridentification();
$strpreview = get_string('createquiz', 'offlinequiz');
$strofflinequizzes = get_string("modulenameplural", "offlinequiz");
$PAGE->set_url('/mod/offlinequiz/createquiz.php?id=' . $cm->id);
$PAGE->set_title($strpreview);
$PAGE->set_heading($course->fullname);
$PAGE->set_pagelayout('report');
// Or 'admin'.
$PAGE->set_cacheable(true);
if ($node = $PAGE->settingsnav->find('mod_offlinequiz_createquiz', navigation_node::TYPE_SETTING)) {
    $node->make_active();
}
if (!($groups = $DB->get_records('offlinequiz_groups', array('offlinequizid' => $offlinequiz->id), 'number', '*', 0, $offlinequiz->numgroups))) {
    print_error('There are no offlinequiz groups', "edit.php?q={$offlinequiz->id}{$amp};sesskey=" . sesskey());
}
// Redmine 2131: Handle download all before any HTML output is produced.
Exemplo n.º 3
0
 public function display($offlinequiz, $cm, $course)
 {
     global $CFG, $OUTPUT, $DB;
     $confirm = optional_param('confirm', 0, PARAM_INT);
     raise_memory_limit(MEMORY_EXTRA);
     // Print header.
     $this->print_header_and_tabs($cm, $course, $offlinequiz, 'regrade');
     offlinequiz_load_useridentification();
     $offlinequizconfig = get_config('offlinequiz');
     $letterstr = 'ABCDEFGHIJKL';
     // Print heading.
     echo $OUTPUT->box_start('linkbox');
     echo $OUTPUT->heading(format_string($offlinequiz->name));
     echo $OUTPUT->heading(get_string('regradingquiz', 'offlinequiz'));
     echo $OUTPUT->box_end('linkbox');
     // Fetch all results.
     $ressql = "SELECT res.*, u.{$offlinequizconfig->ID_field}\n                     FROM {offlinequiz_results} res\n                     JOIN {user} u on u.id = res.userid\n                    WHERE res.offlinequizid = :offlinequizid\n                      AND res.status = 'complete'";
     $resparams = array('offlinequizid' => $offlinequiz->id);
     if (!($results = $DB->get_records_sql($ressql, $resparams))) {
         $url = new moodle_url('/mod/offlinequiz/report.php', array('id' => $cm->id));
         $url->param('mode', 'overview');
         echo $OUTPUT->heading(get_string('noresults', 'offlinequiz'));
         echo $OUTPUT->box_start('linkbox');
         echo $OUTPUT->continue_button($url);
         echo $OUTPUT->box_end('linkbox');
         return true;
     }
     // If we don't have a confirmation we only display the confirm and cancel buttons.
     if (!$confirm) {
         echo $OUTPUT->box_start('linkbox');
         echo $OUTPUT->notification(get_string('regradedisplayexplanation', 'offlinequiz'), 'notifyproblem');
         echo '<br/>';
         $url = new moodle_url('/mod/offlinequiz/report.php', array('id' => $cm->id));
         $url->param('mode', 'regrade');
         $url->param('confirm', 1);
         echo $OUTPUT->single_button($url, get_string('reallyregrade', 'offlinequiz_regrade'));
         echo '<br/>';
         $url = new moodle_url('/mod/offlinequiz/report.php', array('id' => $cm->id));
         $url->param('mode', 'overview');
         echo $OUTPUT->single_button($url, get_string('cancel'));
         echo $OUTPUT->box_end('linkbox');
         return true;
     }
     // Fetch all groups.
     if ($groups = $DB->get_records('offlinequiz_groups', array('offlinequizid' => $offlinequiz->id), 'number', '*', 0, $offlinequiz->numgroups)) {
         foreach ($groups as $group) {
             $sumgrade = offlinequiz_update_sumgrades($offlinequiz, $group->id);
             $groupletter = $letterstr[$group->number - 1];
             $a = new StdClass();
             $a->letter = $groupletter;
             $a->grade = round($sumgrade, $offlinequiz->decimalpoints);
             echo $OUTPUT->notification(get_string('updatedsumgrades', 'offlinequiz', $a), 'notifysuccess');
         }
     }
     // Options for the popup_action.
     $options = array();
     $options['height'] = 1024;
     // Optional.
     $options['width'] = 860;
     // Optional.
     $options['resizable'] = false;
     $saveresult = false;
     // Loop through all results and regrade while printing progress info.
     foreach ($results as $result) {
         set_time_limit(120);
         $sql = "SELECT ogq.questionid, ogq.maxmark \n                      FROM {offlinequiz_group_questions} ogq\n                     WHERE ogq.offlinequizid = :offlinequizid\n                       AND ogq.offlinegroupid = :offlinegroupid";
         $params = array('offlinequizid' => $offlinequiz->id, 'offlinegroupid' => $result->offlinegroupid);
         if (!($questions = $DB->get_records_sql($sql, $params))) {
             print_error("Failed to get questions for regrading!");
         }
         $user = $DB->get_record('user', array('id' => $result->userid));
         echo '<strong>' . get_string('regradingresult', 'offlinequiz', $user->{$offlinequizconfig->ID_field}) . '</strong> ';
         $changed = $this->regrade_result($result, $questions);
         if ($changed) {
             $quba = question_engine::load_questions_usage_by_activity($result->usageid);
             $DB->set_field('offlinequiz_results', 'sumgrades', $quba->get_total_mark(), array('id' => $result->id));
             $url = new moodle_url($CFG->wwwroot . '/mod/offlinequiz/review.php', array('resultid' => $result->id));
             $title = get_string('changed', 'offlinequiz');
             echo $OUTPUT->action_link($url, $title, new popup_action('click', $url, 'review' . $result->id, $options));
         } else {
             echo get_string('done', 'offlinequiz');
         }
         echo '<br />';
         // The following makes sure that the output is sent immediately.
         @flush();
         @ob_flush();
     }
     // Log this action.
     $params = array('objectid' => $cm->id, 'context' => context_module::instance($cm->id), 'other' => array('numberofresults' => count($results), 'offlinequizid' => $offlinequiz->id));
     $event = \mod_offlinequiz\event\results_regraded::create($params);
     $event->trigger();
     $url = new moodle_url($CFG->wwwroot . '/mod/offlinequiz/report.php', array('q' => $offlinequiz->id, 'mode' => 'overview'));
     offlinequiz_update_grades($offlinequiz);
     echo $OUTPUT->box_start('linkbox');
     echo $OUTPUT->single_button($url, get_string('continue'), 'get');
     echo $OUTPUT->box_end('linkbox');
     return true;
 }
Exemplo n.º 4
0
/**
 * Serves a list of participants as a file.
 *
 * @param unknown_type $offlinequiz
 * @param unknown_type $fileformat
 * @param unknown_type $coursecontext
 * @param unknown_type $systemcontext
 */
function offlinequiz_download_partlist($offlinequiz, $fileformat, &$coursecontext, &$systemcontext)
{
    global $CFG, $DB, $COURSE;
    offlinequiz_load_useridentification();
    $offlinequizconfig = get_config('offlinequiz');
    $filename = clean_filename(get_string('participants', 'offlinequiz') . $offlinequiz->id);
    // First get roleids for students from leagcy.
    if (!($roles = get_roles_with_capability('mod/offlinequiz:attempt', CAP_ALLOW, $systemcontext))) {
        print_error("No roles with capability 'mod/offlinequiz:attempt' defined in system context");
    }
    $roleids = array();
    foreach ($roles as $role) {
        $roleids[] = $role->id;
    }
    list($csql, $cparams) = $DB->get_in_or_equal($coursecontext->get_parent_context_ids(true), SQL_PARAMS_NAMED, 'ctx');
    list($rsql, $rparams) = $DB->get_in_or_equal($roleids, SQL_PARAMS_NAMED, 'role');
    $params = array_merge($cparams, $rparams);
    $sql = "SELECT p.id, p.userid, p.listid, u." . $offlinequizconfig->ID_field . ", u.firstname, u.lastname,\n                   u.alternatename, u.middlename, u.firstnamephonetic, u.lastnamephonetic,\n                   u.picture, p.checked\n             FROM {offlinequiz_participants} p,\n                  {offlinequiz_p_lists} pl,\n                  {user} u,\n                  {role_assignments} ra\n            WHERE p.listid = pl.id\n              AND p.userid = u.id\n              AND ra.userid=u.id\n              AND pl.offlinequizid = :offlinequizid\n              AND ra.contextid {$csql}\n              AND ra.roleid {$rsql}";
    $params['offlinequizid'] = $offlinequiz->id;
    // Define table headers.
    $tableheaders = array(get_string('fullname'), get_string($offlinequizconfig->ID_field), get_string('participantslist', 'offlinequiz'), get_string('attemptexists', 'offlinequiz'), get_string('present', 'offlinequiz'));
    if ($fileformat == 'ODS') {
        require_once "{$CFG->libdir}/odslib.class.php";
        $filename .= ".ods";
        // Creating a workbook.
        $workbook = new MoodleODSWorkbook("-");
        // Sending HTTP headers.
        $workbook->send($filename);
        // Creating the first worksheet.
        $sheettitle = get_string('participants', 'offlinequiz');
        $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');
        // Print worksheet headers.
        $colnum = 0;
        foreach ($tableheaders as $item) {
            $myxls->write(0, $colnum, $item, $formatbc);
            $colnum++;
        }
        $rownum = 1;
    } else {
        if ($fileformat == 'Excel') {
            require_once "{$CFG->libdir}/excellib.class.php";
            $filename .= ".xls";
            // Creating a workbook.
            $workbook = new MoodleExcelWorkbook("-");
            // Sending HTTP headers.
            $workbook->send($filename);
            // Creating the first worksheet.
            $sheettitle = get_string('participants', 'offlinequiz');
            $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 = new StdClass();
            $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');
            // Print worksheet headers.
            $colnum = 0;
            foreach ($tableheaders as $item) {
                $myxls->write(0, $colnum, $item, $formatbc);
                $colnum++;
            }
            $rownum = 1;
        } else {
            if ($fileformat == '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 = implode(", ", $tableheaders);
                echo $headers . " \n";
            }
        }
    }
    $lists = $DB->get_records('offlinequiz_p_lists', array('offlinequizid' => $offlinequiz->id));
    $participants = $DB->get_records_sql($sql, $params);
    if ($participants) {
        foreach ($participants as $participant) {
            $userid = $participant->userid;
            $attempt = false;
            $sql = "SELECT COUNT(*)\n                      FROM {offlinequiz_results}\n                     WHERE userid = :userid\n                       AND offlinequizid = :offlinequizid\n                       AND status = 'complete'";
            if ($DB->count_records_sql($sql, array('userid' => $userid, 'offlinequizid' => $offlinequiz->id)) > 0) {
                $attempt = true;
            }
            $row = array(fullname($participant), $participant->{$offlinequizconfig->ID_field}, $lists[$participant->listid]->name, $attempt ? get_string('yes') : get_string('no'), $participant->checked ? get_string('yes') : get_string('no'));
            if ($fileformat == 'Excel' or $fileformat == 'ODS') {
                $colnum = 0;
                foreach ($row as $item) {
                    $myxls->write($rownum, $colnum, $item, $format);
                    $colnum++;
                }
                $rownum++;
            } else {
                if ($fileformat == 'CSV') {
                    $text = implode(", ", $row);
                    echo $text . "\n";
                }
            }
        }
    }
    if ($fileformat == 'Excel' or $fileformat == 'ODS') {
        $workbook->close();
    }
    exit;
}
Exemplo n.º 5
0
 private function print_error_report($offlinequiz)
 {
     global $CFG, $DB, $OUTPUT;
     offlinequiz_load_useridentification();
     $offlinequizconfig = get_config('offlinequiz');
     $nologs = optional_param('nologs', 0, PARAM_INT);
     $pagesize = optional_param('pagesize', 10, PARAM_INT);
     $letterstr = 'ABCDEFGHIJKL';
     require_once 'errorpages_table.php';
     $tableparams = array('q' => $offlinequiz->id, 'mode' => 'rimport', 'action' => 'delete', 'strreallydel' => addslashes(get_string('deletepagecheck', 'offlinequiz')));
     $table = new offlinequiz_selectall_table('mod_offlinequiz_import_report', 'report.php', $tableparams);
     $tablecolumns = array('checkbox', 'counter', 'userkey', 'groupnumber', 'pagenumber', 'time', 'error', 'info', 'link');
     $tableheaders = array('', '#', get_string($offlinequizconfig->ID_field, 'offlinequiz_rimport'), get_string('group'), get_string('page'), get_string('importedon', 'offlinequiz_rimport'), get_string('error'), get_string('info'), '');
     $table->initialbars(true);
     $table->define_columns($tablecolumns);
     $table->define_headers($tableheaders);
     $table->define_baseurl($CFG->wwwroot . '/mod/offlinequiz/report.php?mode=rimport&amp;q=' . $offlinequiz->id . '&amp;nologs=' . $nologs . '&amp;pagesize=' . $pagesize);
     $table->sortable(true, 'time');
     // Sorted by lastname by default.
     $table->initialbars(true);
     $table->column_class('checkbox', 'checkbox');
     $table->column_class('counter', 'counter');
     $table->column_class('username', 'username');
     $table->column_class('group', 'group');
     $table->column_class('page', 'page');
     $table->column_class('time', 'time');
     $table->column_class('error', 'error');
     $table->column_class('link', 'link');
     $table->set_attribute('cellspacing', '0');
     $table->set_attribute('cellpadding', '4');
     $table->set_attribute('id', 'errorpages');
     $table->set_attribute('class', 'errorpages');
     $table->set_attribute('align', 'center');
     $table->set_attribute('border', '1');
     $table->no_sorting('checkbox');
     $table->no_sorting('counter');
     $table->no_sorting('info');
     $table->no_sorting('link');
     // Start working -- this is necessary as soon as the niceties are over.
     $table->setup();
     // Construct the SQL.
     $sql = "SELECT *\n                  FROM {offlinequiz_scanned_pages}\n                 WHERE offlinequizid = :offlinequizid\n                   AND (status = 'error'\n                        OR status = 'suspended'\n                        OR error = 'missingpages')";
     $params = array('offlinequizid' => $offlinequiz->id);
     // Add extra limits due to sorting by question grade.
     if ($sort = $table->get_sql_sort()) {
         if (strpos($sort, 'checkbox') === false && strpos($sort, 'counter') === false && strpos($sort, 'info') === false && strpos($sort, 'link') === false) {
             $sql .= ' ORDER BY ' . $sort;
         }
     }
     $errorpages = $DB->get_records_sql($sql, $params);
     $strtimeformat = get_string('strftimedatetime');
     // Options for the popup_action.
     $options = array();
     $options['height'] = 1200;
     // Optional.
     $options['width'] = 1170;
     // Optional.
     $options['resizable'] = false;
     $counter = 1;
     foreach ($errorpages as $page) {
         if ($page->error == 'filenotfound') {
             $actionlink = '';
         } else {
             if ($page->error == 'missingpages') {
                 $url = new moodle_url($CFG->wwwroot . '/mod/offlinequiz/image.php?pageid=' . $page->id . '&resultid=' . $page->resultid);
                 $title = get_string('showpage', 'offlinequiz_rimport');
             } else {
                 $url = new moodle_url($CFG->wwwroot . '/mod/offlinequiz/correct.php?pageid=' . $page->id);
                 $title = get_string('correcterror', 'offlinequiz_rimport');
             }
             $actionlink = $OUTPUT->action_link($url, $title, new popup_action('click', $url, 'correct' . $page->id, $options));
         }
         $groupstr = '?';
         $groupnumber = $page->groupnumber;
         if ($groupnumber > 0 and $groupnumber <= $offlinequiz->numgroups) {
             $groupstr = $letterstr[$page->groupnumber - 1];
         }
         $errorstr = '';
         if (!empty($page->error)) {
             $errorstr = get_string('error' . $page->error, 'offlinequiz_rimport');
         }
         if ($page->status == 'suspended') {
             $errorstr = get_string('waitingforanalysis', 'offlinequiz_rimport');
         }
         $row = array('<input type="checkbox" name="p' . $page->id . '" value="' . $page->id . '" />', $counter . '&nbsp;', $page->userkey, $groupstr, empty($page->pagenumber) ? '?' : $page->pagenumber, userdate($page->time, $strtimeformat), $errorstr, $page->info, $actionlink);
         $table->add_data($row);
         $counter++;
     }
     if (!$table->print_nothing_to_display()) {
         // Print the table.
         $table->print_html();
     }
 }
Exemplo n.º 6
0
function offlinequiz_evaluation_cron($jobid = 0, $verbose = false)
{
    global $CFG, $DB;
    raise_memory_limit(MEMORY_EXTRA);
    // Only count the jobs with status processing that have been started in the last 24 hours.
    $expiretime = time() - 86400;
    $runningsql = "SELECT COUNT(*)\n                     FROM {offlinequiz_queue}\n                    WHERE status = 'processing'\n                      AND timestart > :expiretime";
    $runningjobs = $DB->count_records_sql($runningsql, array('expiretime' => $expiretime));
    if ($runningjobs >= OFFLINEQUIZ_MAX_CRON_JOBS) {
        echo "Too many jobs running! Exiting!";
        return;
    }
    // TODO do this properly. Just for testing.
    $sql = "SELECT * FROM {offlinequiz_queue} WHERE status = 'new'";
    $params = array();
    if ($jobid) {
        $sql .= ' AND id = :jobid ';
        $params['jobid'] = $jobid;
    }
    $sql .= " ORDER BY id ASC";
    // If there are no new jobs, we simply exit.
    if (!($jobs = $DB->get_records_sql($sql, $params, 0, OFFLINEQUIZ_TOP_QUEUE_JOBS))) {
        if ($verbose) {
            echo get_string('nothingtodo', 'offlinequiz');
        }
        return;
    }
    $numberofjobs = count($jobs);
    if ($verbose) {
        $pbar = new progress_bar('offlinequizcronbar', 500, true);
        $pbar->create();
        $pbar->update(0, $numberofjobs, "Processing job - {0}/{$numberofjobs}.");
    }
    $numberdone = 0;
    foreach ($jobs as $job) {
        // Check whether the status is still 'new' (might have been changed by other cronjob).
        $transaction = $DB->start_delegated_transaction();
        $status = $DB->get_field('offlinequiz_queue', 'status', array('id' => $job->id));
        if ($status == 'new') {
            $DB->set_field('offlinequiz_queue', 'status', 'processing', array('id' => $job->id));
            $job->timestart = time();
            $DB->set_field('offlinequiz_queue', 'timestart', $job->timestart, array('id' => $job->id));
            $alreadydone = false;
        } else {
            $alreadydone = true;
        }
        $transaction->allow_commit();
        // If the job is still new, process it!
        if (!$alreadydone) {
            // Set up the context for this job.
            if (!($offlinequiz = $DB->get_record('offlinequiz', array('id' => $job->offlinequizid)))) {
                $DB->set_field('offlinequiz_queue', 'status', 'error', array('id' => $job->id));
                $DB->set_field('offlinequiz_queue', 'info', 'offlinequiz not found', array('id' => $job->id));
                continue;
            }
            if (!($course = $DB->get_record('course', array('id' => $offlinequiz->course)))) {
                $DB->set_field('offlinequiz_queue', 'status', 'error', array('id' => $job->id));
                $DB->set_field('offlinequiz_queue', 'info', 'course not found', array('id' => $job->id));
                continue;
            }
            if (!($cm = get_coursemodule_from_instance("offlinequiz", $offlinequiz->id, $course->id))) {
                $DB->set_field('offlinequiz_queue', 'status', 'error', array('id' => $job->id));
                $DB->set_field('offlinequiz_queue', 'info', 'course module found', array('id' => $job->id));
                continue;
            }
            if (!($context = context_module::instance($cm->id))) {
                $DB->set_field('offlinequiz_queue', 'status', 'error', array('id' => $job->id));
                $DB->set_field('offlinequiz_queue', 'info', 'context not found', array('id' => $job->id));
                continue;
            }
            if (!($groups = $DB->get_records('offlinequiz_groups', array('offlinequizid' => $offlinequiz->id), 'number', '*', 0, $offlinequiz->numgroups))) {
                $DB->set_field('offlinequiz_queue', 'status', 'error', array('id' => $job->id));
                $DB->set_field('offlinequiz_queue', 'info', 'no offlinequiz groups found', array('id' => $job->id));
                continue;
            }
            $coursecontext = context_course::instance($course->id);
            offlinequiz_load_useridentification();
            // TODO.
            $jobdata = $DB->get_records_sql("\n                    SELECT *\n                      FROM {offlinequiz_queue_data}\n                     WHERE queueid = :queueid\n                       AND status = 'new'", array('queueid' => $job->id));
            list($maxquestions, $maxanswers, $formtype, $questionsperpage) = offlinequiz_get_question_numbers($offlinequiz, $groups);
            $dirname = '';
            $doubleentry = 0;
            foreach ($jobdata as $data) {
                $starttime = time();
                $DB->set_field('offlinequiz_queue_data', 'status', 'processing', array('id' => $data->id));
                // We remember the directory name to be able to remove it later.
                if (empty($dirname)) {
                    $pathparts = pathinfo($data->filename);
                    $dirname = $pathparts['dirname'];
                }
                set_time_limit(120);
                try {
                    // Create a new scanner for every page.
                    $scanner = new offlinequiz_page_scanner($offlinequiz, $context->id, $maxquestions, $maxanswers);
                    // Try to load the image file.
                    echo 'job ' . $job->id . ': evaluating ' . $data->filename . "\n";
                    $scannedpage = $scanner->load_image($data->filename);
                    if ($scannedpage->status == 'ok') {
                        echo 'job ' . $job->id . ': image loaded ' . $scannedpage->filename . "\n";
                    } else {
                        if ($scannedpage->error == 'filenotfound') {
                            echo 'job ' . $job->id . ': image file not found: ' . $scannedpage->filename . "\n";
                        }
                    }
                    // Unset the origfilename because we don't need it in the DB.
                    unset($scannedpage->origfilename);
                    $scannedpage->offlinequizid = $offlinequiz->id;
                    // If we could load the image file, the status is 'ok', so we can check the page for errors.
                    if ($scannedpage->status == 'ok') {
                        // We autorotate so check_scanned_page will return a potentially new scanner and the scannedpage.
                        list($scanner, $scannedpage) = offlinequiz_check_scanned_page($offlinequiz, $scanner, $scannedpage, $job->importuserid, $coursecontext, true);
                    } else {
                        if (property_exists($scannedpage, 'id') && !empty($scannedpage->id)) {
                            $DB->update_record('offlinequiz_scanned_pages', $scannedpage);
                        } else {
                            $scannedpage->id = $DB->insert_record('offlinequiz_scanned_pages', $scannedpage);
                        }
                    }
                    echo 'job ' . $job->id . ': scannedpage id ' . $scannedpage->id . "\n";
                    // If the status is still 'ok', we can process the answers. This potentially submits the page and
                    // checks whether the result for a student is complete.
                    if ($scannedpage->status == 'ok') {
                        // We can process the answers and submit them if possible.
                        $scannedpage = offlinequiz_process_scanned_page($offlinequiz, $scanner, $scannedpage, $job->importuserid, $questionsperpage, $coursecontext, true);
                        echo 'job ' . $job->id . ': processed answers for ' . $scannedpage->id . "\n";
                    } else {
                        if ($scannedpage->status == 'error' && $scannedpage->error == 'resultexists') {
                            // Already process the answers but don't submit them.
                            $scannedpage = offlinequiz_process_scanned_page($offlinequiz, $scanner, $scannedpage, $job->importuserid, $questionsperpage, $coursecontext, false);
                            // Compare the old and the new result wrt. the choices.
                            $scannedpage = offlinequiz_check_different_result($scannedpage);
                        }
                    }
                    // If there is something to correct then store the hotspots for retrieval in correct.php.
                    if ($scannedpage->status != 'ok' && $scannedpage->error != 'couldnotgrab' && $scannedpage->error != 'notadjusted' && $scannedpage->error != 'grouperror') {
                        $scanner->store_hotspots($scannedpage->id);
                    }
                    if ($scannedpage->status == 'ok' || $scannedpage->status == 'submitted' || $scannedpage->status == 'suspended' || $scannedpage->error == 'missingpages') {
                        // Mark the file as processed.
                        $DB->set_field('offlinequiz_queue_data', 'status', 'processed', array('id' => $data->id));
                    } else {
                        $DB->set_field('offlinequiz_queue_data', 'status', 'error', array('id' => $data->id));
                        $DB->set_field('offlinequiz_queue_data', 'error', $scannedpage->error, array('id' => $data->id));
                    }
                    if ($scannedpage->error == 'doublepage') {
                        $doubleentry++;
                    }
                } catch (Exception $e) {
                    echo 'job ' . $job->id . ': ' . $e->getMessage() . "\n";
                    $DB->set_field('offlinequiz_queue_data', 'status', 'error', array('id' => $data->id));
                    $DB->set_field('offlinequiz_queue_data', 'error', 'couldnotgrab', array('id' => $data->id));
                    $DB->set_field('offlinequiz_queue_data', 'info', $e->getMessage(), array('id' => $data->id));
                    $scannedpage->status = 'error';
                    $scannedpage->error = 'couldnotgrab';
                    if ($scannedpage->id) {
                        $DB->update_record('offlinequiz_scanned_pages', $scannedpage);
                    } else {
                        $DB->insert_record('offlinequiz_scanned_pages', $scannedpage);
                    }
                }
            }
            // End foreach jobdata.
            offlinequiz_update_grades($offlinequiz);
            $job->timefinish = time();
            $DB->set_field('offlinequiz_queue', 'timefinish', $job->timefinish, array('id' => $job->id));
            $job->status = 'finished';
            $DB->set_field('offlinequiz_queue', 'status', 'finished', array('id' => $job->id));
            echo date('Y-m-d-H:i') . ": Import queue with id {$job->id} imported.\n\n";
            if ($user = $DB->get_record('user', array('id' => $job->importuserid))) {
                $mailtext = get_string('importisfinished', 'offlinequiz', format_text($offlinequiz->name, FORMAT_PLAIN));
                // How many pages have been imported successfully.
                $countsql = "SELECT COUNT(id)\n                               FROM {offlinequiz_queue_data}\n                              WHERE queueid = :queueid\n                                AND status = 'processed'";
                $params = array('queueid' => $job->id);
                $mailtext .= "\n\n" . get_string('importnumberpages', 'offlinequiz', $DB->count_records_sql($countsql, $params));
                // How many pages have an error.
                $countsql = "SELECT COUNT(id)\n                               FROM {offlinequiz_queue_data}\n                              WHERE queueid = :queueid\n                                AND status = 'error'";
                $mailtext .= "\n" . get_string('importnumberverify', 'offlinequiz', $DB->count_records_sql($countsql, $params));
                $mailtext .= "\n" . get_string('importnumberexisting', 'offlinequiz', $doubleentry);
                $linkoverview = "{$CFG->wwwroot}/mod/offlinequiz/report.php?q={$job->offlinequizid}&mode=overview";
                $mailtext .= "\n\n" . get_string('importlinkresults', 'offlinequiz', $linkoverview);
                $linkupload = "{$CFG->wwwroot}/mod/offlinequiz/report.php?q={$job->offlinequizid}&mode=rimport";
                $mailtext .= "\n" . get_string('importlinkverify', 'offlinequiz', $linkupload);
                $mailtext .= "\n\n" . get_string('importtimestart', 'offlinequiz', userdate($job->timestart));
                $mailtext .= "\n" . get_string('importtimefinish', 'offlinequiz', userdate($job->timefinish));
                email_to_user($user, $CFG->noreplyaddress, get_string('importmailsubject', 'offlinequiz'), $mailtext);
            }
        }
        // End !alreadydone.
        $numberdone++;
        if ($verbose) {
            ob_flush();
            $pbar->update($numberdone, $numberofjobs, "Processing job - {$numberdone}/{$numberofjobs}.");
        }
    }
    // End foreach.
}