Example #1
0
    /**
     * Called before starting to upgrade all the attempts at a particular quiz.
     * @param int $done the number of quizzes processed so far.
     * @param int $outof the total number of quizzes to process.
     * @param int $quizid the id of the quiz that is about to be processed.
     */
    protected function print_progress($done, $outof, $quizid) {
        if (is_null($this->progressbar)) {
            $this->progressbar = new progress_bar('qe2upgrade');
            $this->progressbar->create();
        }

        gc_collect_cycles(); // This was really helpful in PHP 5.2. Perhaps remove.
        $a = new stdClass();
        $a->done = $done;
        $a->outof = $outof;
        $a->info = $quizid;
        $this->progressbar->update($done, $outof, get_string('upgradingquizattempts', 'quiz', $a));
    }
/**
 * Installation code for the ddmarker question type. It converts all existing imagetarget questions to ddmarker
 */
function xmldb_qtype_ddmarker_install()
{
    global $DB, $OUTPUT;
    $from = 'FROM {question_categories} cat, {question} q';
    $where = ' WHERE q.qtype = \'imagetarget\' AND q.category =  cat.id ';
    $sql = 'SELECT q.*, cat.contextid ' . $from . $where . 'ORDER BY cat.id, q.name';
    $questions = $DB->get_records_sql($sql);
    if (!empty($questions)) {
        require_once dirname(__FILE__) . '/../lib.php';
        $dragssql = 'SELECT drag.* ' . $from . ', {qtype_ddmarker_drags} drag' . $where . ' AND drag.questionid = q.id';
        $drags = xmldb_qtype_ddmarker_index_array_of_records_by_key('questionid', $DB->get_records_sql($dragssql));
        $dropssql = 'SELECT drp.* ' . $from . ', {qtype_ddmarker_drops} drp' . $where . ' AND drp.questionid = q.id';
        $drops = xmldb_qtype_ddmarker_index_array_of_records_by_key('questionid', $DB->get_records_sql($dropssql));
        $answerssql = 'SELECT answer.* ' . $from . ', {question_answers} answer' . $where . ' AND answer.question = q.id';
        $answers = xmldb_qtype_ddmarker_index_array_of_records_by_key('question', $DB->get_records_sql($answerssql));
        $imgfiles = $DB->get_records_sql_menu('SELECT question, qimage FROM {question_imagetarget}');
        $progressbar = new progress_bar('qtype_ddmarker_convert_from_imagetarget');
        $progressbar->create();
        $done = 0;
        foreach ($questions as $question) {
            qtype_ddmarker_convert_image_target_question($question, $imgfiles[$question->id], $answers[$question->id]);
            $done++;
            $progressbar->update($done, count($questions), get_string('convertingimagetargetquestion', 'qtype_ddmarker', $question));
        }
        list($qsql, $qparams) = $DB->get_in_or_equal(array_keys($questions));
        $DB->delete_records_select('question_answers', 'question ' . $qsql, $qparams);
        $dbman = $DB->get_manager();
        $dbman->drop_table(new xmldb_table('question_imagetarget'));
    }
}
function xmldb_offlinequiz_upgrade($oldversion = 0)
{
    global $CFG, $THEME, $DB, $OUTPUT;
    $dbman = $DB->get_manager();
    // And upgrade begins here. For each one, you'll need one
    // Block of code similar to the next one. Please, delete
    // This comment lines once this file start handling proper
    // Upgrade code.
    // ONLY UPGRADE FROM Moodle 1.9.x (module version 2009042100) is supported.
    if ($oldversion < 2009120700) {
        // Define field counter to be added to offlinequiz_i_log.
        $table = new xmldb_table('offlinequiz_i_log');
        $field = new xmldb_field('counter');
        $field->set_attributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'rawdata');
        // Launch add field counter.
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }
        // Define field corners to be added to offlinequiz_i_log.
        $field = new xmldb_field('corners');
        $field->set_attributes(XMLDB_TYPE_CHAR, '50', null, null, null, null, 'counter');
        // Launch add field corners.
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }
        // Define field pdfintro to be added to offlinequiz.
        $table = new xmldb_table('offlinequiz');
        $field = new xmldb_field('pdfintro');
        $field->set_attributes(XMLDB_TYPE_TEXT, 'small', null, null, null, null, 'intro');
        // Launch add field pdfintro.
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2009120700, 'offlinequiz');
    }
    if ($oldversion < 2010082900) {
        // Define table offlinequiz_p_list to be created.
        $table = new xmldb_table('offlinequiz_p_list');
        // Adding fields to table offlinequiz_p_list.
        $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
        $table->add_field('offlinequiz', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
        $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null, null, null);
        $table->add_field('list', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '1');
        // Adding keys to table offlinequiz_p_list.
        $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
        // Launch create table for offlinequiz_p_list.
        $dbman->create_table($table);
        // Define field position to be dropped from offlinequiz_participants.
        $table = new xmldb_table('offlinequiz_participants');
        $field = new xmldb_field('position');
        // Launch drop field position.
        $dbman->drop_field($table, $field);
        // Define field page to be dropped from offlinequiz_participants.
        $table = new xmldb_table('offlinequiz_participants');
        $field = new xmldb_field('page');
        // Launch drop field page.
        $dbman->drop_field($table, $field);
        // Define field list to be added to offlinequiz_participants.
        $table = new xmldb_table('offlinequiz_participants');
        $field = new xmldb_field('list');
        $field->set_attributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '1', 'userid');
        // Launch add field list.
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2010082900, 'offlinequiz');
    }
    if ($oldversion < 2010090600) {
        // Define index offlinequiz (not unique) to be added to offlinequiz_p_list.
        $table = new xmldb_table('offlinequiz_p_list');
        $index = new XMLDBIndex('offlinequiz');
        $index->set_attributes(XMLDB_INDEX_NOTUNIQUE, array('offlinequiz'));
        // Launch add index offlinequiz.
        if (!$dbman->index_exists($table, $index)) {
            $dbman->add_index($table, $index);
        }
        $index = new XMLDBIndex('list');
        $index->set_attributes(XMLDB_INDEX_NOTUNIQUE, array('list'));
        // Launch add index list.
        if (!$dbman->index_exists($table, $index)) {
            $dbman->add_index($table, $index);
        }
        // Define index offlinequiz (not unique) to be added to offlinequiz_participants.
        $table = new xmldb_table('offlinequiz_participants');
        $index = new XMLDBIndex('offlinequiz');
        $index->set_attributes(XMLDB_INDEX_NOTUNIQUE, array('offlinequiz'));
        // Launch add index offlinequiz.
        if (!$dbman->index_exists($table, $index)) {
            $dbman->add_index($table, $index);
        }
        $index = new XMLDBIndex('list');
        $index->set_attributes(XMLDB_INDEX_NOTUNIQUE, array('list'));
        // Launch add index list.
        if (!$dbman->index_exists($table, $index)) {
            $dbman->add_index($table, $index);
        }
        $index = new XMLDBIndex('userid');
        $index->set_attributes(XMLDB_INDEX_NOTUNIQUE, array('userid'));
        // Launch add index list.
        if (!$dbman->index_exists($table, $index)) {
            $dbman->add_index($table, $index);
        }
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2010090600, 'offlinequiz');
    }
    if ($oldversion < 2011021400) {
        // Define field fileformat to be added to offlinequiz.
        $table = new xmldb_table('offlinequiz');
        $field = new xmldb_field('fileformat');
        $field->set_attributes(XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'timemodified');
        // Launch add field fileformat.
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2011021400, 'offlinequiz');
    }
    if ($oldversion < 2011032900) {
        // Define field page to be added to offlinequiz_i_log.
        $table = new xmldb_table('offlinequiz_i_log');
        $field = new xmldb_field('page');
        $field->set_attributes(XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'corners');
        // Launch add field page.
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }
        // Define field username to be added to offlinequiz_i_log.
        $field = new xmldb_field('username');
        $field->set_attributes(XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null, 'page');
        // Launch add field username.
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }
        // Define index username (not unique) to be added to offlinequiz_i_log.
        $index = new XMLDBIndex('username');
        $index->set_attributes(XMLDB_INDEX_NOTUNIQUE, array('username'));
        // Launch add index username.
        if (!$dbman->index_exists($table, $index)) {
            $dbman->add_index($table, $index);
        }
        // Define field showgrades to be added to offlinequiz.
        $table = new xmldb_table('offlinequiz');
        $field = new xmldb_field('showgrades');
        $field->set_attributes(XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'fileformat');
        // Launch add field showgrades.
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2011032900, 'offlinequiz');
    }
    if ($oldversion < 2011081700) {
        // Define field showtutorial to be added to offlinequiz.
        $table = new xmldb_table('offlinequiz');
        $field = new xmldb_field('showtutorial');
        $field->set_attributes(XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'showgrades');
        // Launch add field showtutorial.
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2011081700, 'offlinequiz');
    }
    // ------------------------------------------------------
    // UPGRADE for Moodle 2.0 module starts here.
    // ------------------------------------------------------
    // First we do the changes to the main table 'offlinequiz'.
    // ------------------------------------------------------
    if ($oldversion < 2012010100) {
        // Define field docscreated to be added to offlinequiz.
        $table = new xmldb_table('offlinequiz');
        $field = new xmldb_field('docscreated', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'questionsperpage');
        // Conditionally launch add field docscreated.
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2012010100, 'offlinequiz');
    }
    // Fill the new field docscreated.
    if ($oldversion < 2012010101) {
        $offlinequizzes = $DB->get_records('offlinequiz');
        foreach ($offlinequizzes as $offlinequiz) {
            $dirname = $CFG->dataroot . '/' . $offlinequiz->course . '/moddata/offlinequiz/' . $offlinequiz->id . '/pdfs';
            // If the answer pdf file for group 1 exists then we have created the documents.
            if (file_exists($dirname . '/answer-a.pdf')) {
                $DB->set_field('offlinequiz', 'docscreated', 1, array('id' => $offlinequiz->id));
            }
        }
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2012010101, 'offlinequiz');
    }
    if ($oldversion < 2012010105) {
        // Define table offlinequiz_reports to be created.
        $table = new xmldb_table('offlinequiz_reports');
        // Adding fields to table offlinequiz_reports.
        $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
        $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null);
        $table->add_field('displayorder', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);
        $table->add_field('lastcron', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
        $table->add_field('cron', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
        $table->add_field('capability', XMLDB_TYPE_CHAR, '255', null, null, null, null);
        // Adding keys to table offlinequiz_reports.
        $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
        // Adding indexes to table offlinequiz_reports.
        // $table->add_index('name', XMLDB_INDEX_UNIQUE, array('name'));.
        // Conditionally launch create table for offlinequiz_reports.
        if (!$dbman->table_exists($table)) {
            $dbman->create_table($table);
        }
        if (!$DB->get_records_sql("SELECT * FROM {offlinequiz_reports} WHERE name = 'overview'", array())) {
            $record = new stdClass();
            $record->name = 'overview';
            $record->displayorder = '10000';
            $DB->insert_record('offlinequiz_reports', $record);
        }
        if (!$DB->get_records_sql("SELECT * FROM {offlinequiz_reports} WHERE name = 'rimport'", array())) {
            $record = new stdClass();
            $record->name = 'rimport';
            $record->displayorder = '9000';
            $DB->insert_record('offlinequiz_reports', $record);
        }
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2012010105, 'offlinequiz');
    }
    // Now we create all the new tables.
    // Create table offlinequiz_groups.
    if ($oldversion < 2012010200) {
        echo $OUTPUT->notification('Creating new tables', 'notifysuccess');
        // Define table offlinequiz_groups to be created.
        $table = new xmldb_table('offlinequiz_groups');
        // Adding fields to table offlinequiz_groups.
        $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
        $table->add_field('offlinequizid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);
        $table->add_field('number', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
        $table->add_field('sumgrades', XMLDB_TYPE_NUMBER, '10, 5', null, XMLDB_NOTNULL, null, '0');
        $table->add_field('numberofpages', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
        $table->add_field('templateusageid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
        // Adding keys to table offlinequiz_groups.
        $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
        // Adding indexes to table offlinequiz_groups.
        $table->add_index('offlinequizid', XMLDB_INDEX_NOTUNIQUE, array('offlinequizid'));
        // Conditionally launch create table for offlinequiz_groups.
        if (!$dbman->table_exists($table)) {
            $dbman->create_table($table);
        }
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2012010200, 'offlinequiz');
    }
    // Create table offlinequiz_group_questions.
    if ($oldversion < 2012010300) {
        // Define table offlinequiz_group_questions to be created.
        $table = new xmldb_table('offlinequiz_group_questions');
        // Adding fields to table offlinequiz_group_questions.
        $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
        $table->add_field('offlinequizid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);
        $table->add_field('offlinegroupid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);
        $table->add_field('questionid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);
        $table->add_field('position', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '1');
        $table->add_field('pagenumber', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, null, null, null);
        $table->add_field('usageslot', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, null, null, null);
        // Adding keys to table offlinequiz_group_questions.
        $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
        // Adding indexes to table offlinequiz_group_questions.
        $table->add_index('offlinequiz', XMLDB_INDEX_NOTUNIQUE, array('offlinequizid'));
        // Conditionally launch create table for offlinequiz_group_questions.
        if (!$dbman->table_exists($table)) {
            $dbman->create_table($table);
        }
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2012010300, 'offlinequiz');
    }
    if ($oldversion < 2012010400) {
        // Define table offlinequiz_scanned_pages to be created.
        $table = new xmldb_table('offlinequiz_scanned_pages');
        // Adding fields to table offlinequiz_scanned_pages.
        $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
        $table->add_field('offlinequizid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);
        $table->add_field('resultid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, null);
        $table->add_field('filename', XMLDB_TYPE_CHAR, '1000', null, null, null, null);
        $table->add_field('warningfilename', XMLDB_TYPE_CHAR, '1000', null, null, null, null);
        $table->add_field('groupnumber', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, null, null, null);
        $table->add_field('userkey', XMLDB_TYPE_CHAR, '255', null, null, null, null);
        $table->add_field('pagenumber', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, null, null, null);
        $table->add_field('time', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
        $table->add_field('status', XMLDB_TYPE_CHAR, '20', null, XMLDB_NOTNULL, null, null);
        $table->add_field('error', XMLDB_TYPE_CHAR, '255', null, null, null, null);
        $table->add_field('info', XMLDB_TYPE_TEXT, 'medium', null, null, null, null);
        // Adding keys to table offlinequiz_scanned_pages.
        $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
        // Adding indexes to table offlinequiz_scanned_pages.
        $table->add_index('offlinequizid', XMLDB_INDEX_NOTUNIQUE, array('offlinequizid'));
        // Conditionally launch create table for offlinequiz_scanned_pages.
        if (!$dbman->table_exists($table)) {
            $dbman->create_table($table);
        }
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2012010400, 'offlinequiz');
    }
    if ($oldversion < 2012010500) {
        // Define table offlinequiz_choices to be created.
        $table = new xmldb_table('offlinequiz_choices');
        // Adding fields to table offlinequiz_choices.
        $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
        $table->add_field('scannedpageid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);
        $table->add_field('slotnumber', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);
        $table->add_field('choicenumber', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);
        $table->add_field('value', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, null);
        // Adding keys to table offlinequiz_choices.
        $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
        // Adding indexes to table offlinequiz_choices.
        $table->add_index('scannedpageid', XMLDB_INDEX_NOTUNIQUE, array('scannedpageid'));
        // Conditionally launch create table for offlinequiz_choices.
        if (!$dbman->table_exists($table)) {
            $dbman->create_table($table);
        }
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2012010500, 'offlinequiz');
    }
    if ($oldversion < 2012010600) {
        // Define table offlinequiz_page_corners to be created.
        $table = new xmldb_table('offlinequiz_page_corners');
        // Adding fields to table offlinequiz_page_corners.
        $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
        $table->add_field('scannedpageid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);
        $table->add_field('x', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
        $table->add_field('y', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
        $table->add_field('position', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);
        // Adding keys to table offlinequiz_page_corners.
        $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
        // Conditionally launch create table for offlinequiz_page_corners.
        if (!$dbman->table_exists($table)) {
            $dbman->create_table($table);
        }
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2012010600, 'offlinequiz');
    }
    if ($oldversion < 2012010700) {
        // Define table offlinequiz_results to be created.
        $table = new xmldb_table('offlinequiz_results');
        // Adding fields to table offlinequiz_results.
        $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
        $table->add_field('offlinequizid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);
        $table->add_field('offlinegroupid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);
        $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);
        $table->add_field('sumgrades', XMLDB_TYPE_NUMBER, '10, 5', null, null, null, null);
        $table->add_field('usageid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);
        $table->add_field('teacherid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);
        $table->add_field('attendant', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
        $table->add_field('status', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
        $table->add_field('timestart', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
        $table->add_field('timefinish', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, '0');
        $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
        $table->add_field('preview', XMLDB_TYPE_INTEGER, '3', XMLDB_UNSIGNED, null, null, '0');
        // Adding keys to table offlinequiz_results.
        $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
        // Conditionally launch create table for offlinequiz_results.
        if (!$dbman->table_exists($table)) {
            $dbman->create_table($table);
        }
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2012010700, 'offlinequiz');
    }
    if ($oldversion < 2012010800) {
        // Define table offlinequiz_scanned_p_pages to be created.
        $table = new xmldb_table('offlinequiz_scanned_p_pages');
        // Adding fields to table offlinequiz_scanned_p_pages.
        $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
        $table->add_field('offlinequizid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);
        $table->add_field('listnumber', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, null, null, null);
        $table->add_field('filename', XMLDB_TYPE_CHAR, '1000', null, null, null, null);
        $table->add_field('time', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
        $table->add_field('status', XMLDB_TYPE_TEXT, 'small', null, XMLDB_NOTNULL, null);
        $table->add_field('error', XMLDB_TYPE_TEXT, 'small', null, null, null, null);
        // Adding keys to table offlinequiz_scanned_p_pages.
        $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
        // Conditionally launch create table for offlinequiz_scanned_p_pages.
        if (!$dbman->table_exists($table)) {
            $dbman->create_table($table);
        }
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2012010800, 'offlinequiz');
    }
    if ($oldversion < 2012010900) {
        // Define table offlinequiz_p_choices to be created.
        $table = new xmldb_table('offlinequiz_p_choices');
        // Adding fields to table offlinequiz_p_choices.
        $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
        $table->add_field('scannedppageid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);
        $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, null);
        $table->add_field('value', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, '0');
        // Adding keys to table offlinequiz_p_choices.
        $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
        // Conditionally launch create table for offlinequiz_p_choices.
        if (!$dbman->table_exists($table)) {
            $dbman->create_table($table);
        }
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2012010900, 'offlinequiz');
    }
    if ($oldversion < 2012011000) {
        // Define table offlinequiz_p_lists to be created.
        $table = new xmldb_table('offlinequiz_p_lists');
        // Adding fields to table offlinequiz_p_lists.
        $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
        $table->add_field('offlinequizid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
        $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null);
        $table->add_field('number', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '1');
        $table->add_field('filename', XMLDB_TYPE_CHAR, '1000', null, null, null, null);
        // Adding keys to table offlinequiz_p_lists.
        $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
        // Adding indexes to table offlinequiz_p_lists.
        $table->add_index('offlinequizid', XMLDB_INDEX_NOTUNIQUE, array('offlinequizid'));
        // Conditionally launch create table for offlinequiz_p_lists.
        if (!$dbman->table_exists($table)) {
            $dbman->create_table($table);
        }
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2012011000, 'offlinequiz');
    }
    // ------------------------------------------------------
    // New we rename fields in old tables.
    // ------------------------------------------------------
    // Rename fields in offlinequiz_queue table.
    if ($oldversion < 2012020100) {
        echo $OUTPUT->notification('Renaming fields in old tables.', 'notifysuccess');
        // Rename field offlinequiz on table offlinequiz_queue to NEWNAMEGOESHERE.
        $table = new xmldb_table('offlinequiz_queue');
        $field = new xmldb_field('offlinequiz');
        $field->set_attributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'timefinish');
        // Launch rename field offlinequiz.
        $dbman->rename_field($table, $field, 'offlinequizid');
        $field = new xmldb_field('importadmin');
        $field->set_attributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'id');
        // Launch rename field importadmin.
        $dbman->rename_field($table, $field, 'importuserid');
        // New status field.
        $field = new xmldb_field('status', XMLDB_TYPE_TEXT, 'small', null, null, null, 'processed', 'timefinish');
        // Conditionally launch add field status.
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2012020100, 'offlinequiz');
    }
    // Add and rename fields in table offlinquiz_queue_data.
    if ($oldversion < 2012020200) {
        // Define field status to be added to offlinequiz_queue_data.
        $table = new xmldb_table('offlinequiz_queue_data');
        $field = new xmldb_field('status', XMLDB_TYPE_TEXT, 'small', null, XMLDB_NOTNULL, null, 'ok', 'filename');
        // Conditionally launch add field status.
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        } else {
            $dbman->change_field_type($table, $field);
            $dbman->change_field_precision($table, $field);
            $dbman->change_field_notnull($table, $field);
            $dbman->change_field_unsigned($table, $field);
        }
        // Add new field 'error'.
        $field = new xmldb_field('error', XMLDB_TYPE_TEXT, 'small', null, null, null, null, 'status');
        // Conditionally launch add field error.
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }
        // Rename field queue to queueid.
        $field = new xmldb_field('queue', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'id');
        // Launch rename field queueid.
        $dbman->rename_field($table, $field, 'queueid');
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2012020200, 'offlinequiz');
    }
    // Rename field list on table offlinequiz_participants to listid.
    if ($oldversion < 2012020300) {
        // Rename field list on table offlinequiz_participants to listid.
        $table = new xmldb_table('offlinequiz_participants');
        $field = new xmldb_field('list', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'id');
        // Launch rename field listid.
        $dbman->rename_field($table, $field, 'listid');
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2012020300, 'offlinequiz');
    }
    // Migrate the old lists of participants to the new table offlinequiz_p_lists (with 's').
    if ($oldversion < 2012020400) {
        $oldplists = $DB->get_records('offlinequiz_p_list');
        foreach ($oldplists as $oldplist) {
            $newplist = new StdClass();
            $newplist->offlinequizid = $oldplist->offlinequiz;
            $newplist->name = $oldplist->name;
            $newplist->number = $oldplist->list;
            // NOTE.
            // We don't set filename because we can always recreate the PDF files if needed.
            $newplist->id = $DB->insert_record('offlinequiz_p_lists', $newplist);
            // Get all the participants linked to the old list and link them to the new list in offlinequiz_p_lists.
            if ($oldparts = $DB->get_records('offlinequiz_participants', array('listid' => $oldplist->id))) {
                foreach ($oldparts as $oldpart) {
                    $oldpart->listid = $newplist->id;
                    $DB->update_record('offlinequiz_participants', $oldpart);
                }
            }
        }
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2012020400, 'offlinequiz');
    }
    // Check if there are inconsistencies in the DB, i.e. uniqueids used by both quizzes and offlinequizzes.
    if ($oldversion < 2012020410) {
        $sql = 'SELECT uniqueid
        FROM {offlinequiz_attempts} qa WHERE
        EXISTS (SELECT id from {quiz_attempts} where uniqueid = qa.uniqueid)';
        $doubleids = $DB->get_fieldset_sql($sql, array());
        // For each double uniqueid create a new uniqueid and change the fields in the tables.
        // Offlinequiz_attempts, question_sessions and question_states.
        echo $OUTPUT->notification('Fixing ' . count($doubleids) . ' question attempt uniqueids that are not unique', 'notifysuccess');
        foreach ($doubleids as $doubleid) {
            echo $doubleid . ', ';
            if ($usage = $DB->get_record('question_usages', array('id' => $doubleid))) {
                $transaction = $DB->start_delegated_transaction();
                unset($usage->id);
                $usage->id = $DB->insert_record('question_usages', $usage);
                $DB->set_field_select('offlinequiz_attempts', 'uniqueid', $usage->id, 'uniqueid = :oldid', array('oldid' => $doubleid));
                $DB->set_field_select('question_states', 'attempt', $usage->id, 'attempt = :oldid', array('oldid' => $doubleid));
                $DB->set_field_select('question_sessions', 'attemptid', $usage->id, 'attemptid = :oldid', array('oldid' => $doubleid));
                $transaction->allow_commit();
            }
        }
        upgrade_mod_savepoint(true, 2012020410, 'offlinequiz');
    }
    // -----------------------------------------------------
    //  Update the contextid field in question_usages (compare lib/db/upgrade.php lines 6108 following).
    // -----------------------------------------------------
    if ($oldversion < 2012020500) {
        echo $OUTPUT->notification('Fixing question usages context ID', 'notifysuccess');
        // Update the component field if necessary.
        $DB->set_field('question_usages', 'component', 'mod_offlinequiz', array('component' => 'offlinequiz'));
        // Populate the contextid field.
        $offlinequizmoduleid = $DB->get_field('modules', 'id', array('name' => 'offlinequiz'));
        $DB->execute("\n                UPDATE {question_usages} SET contextid = (\n                SELECT ctx.id\n                FROM {context} ctx\n                JOIN {course_modules} cm ON cm.id = ctx.instanceid AND cm.module = {$offlinequizmoduleid}\n                JOIN {offlinequiz_attempts} quiza ON quiza.offlinequiz = cm.instance\n                WHERE ctx.contextlevel = " . CONTEXT_MODULE . "\n                AND quiza.uniqueid = {question_usages}.id)\n                WHERE (\n                SELECT ctx.id\n                FROM {context} ctx\n                JOIN {course_modules} cm ON cm.id = ctx.instanceid AND cm.module = {$offlinequizmoduleid}\n                JOIN {offlinequiz_attempts} quiza ON quiza.offlinequiz = cm.instance\n                WHERE ctx.contextlevel = " . CONTEXT_MODULE . "\n                AND quiza.uniqueid = {question_usages}.id) IS NOT NULL\n                ");
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2012020500, 'offlinequiz');
    }
    // -----------------------------------------------------
    //  Now we migrate data from the old to the new tables.
    // -----------------------------------------------------
    // We have to delete redundant question instances from offlinequizzes because they are incompatible with the new code.
    if ($oldversion < 2012030100) {
        echo $OUTPUT->notification('Migrating old offline quizzes to new offline quizzes..', 'notifysuccess');
        require_once $CFG->dirroot . '/mod/offlinequiz/db/upgradelib.php';
        offlinequiz_remove_redundant_q_instances();
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2012030100, 'offlinequiz');
    }
    // Migrate all entries in the offlinequiz_group table to the new tables offlinequiz_groups  and offlinequiz_group_questions.
    if ($oldversion < 2012030101) {
        echo $OUTPUT->notification('Creating new offlinequiz groups', 'notifysuccess');
        $offlinequizzes = $DB->get_records('offlinequiz');
        $counter = 0;
        foreach ($offlinequizzes as $offlinequiz) {
            if (!$DB->get_records('offlinequiz_groups', array('offlinequizid' => $offlinequiz->id))) {
                echo '.';
                $counter++;
                flush();
                ob_flush();
                if ($counter % 100 == 0) {
                    echo "<br/>\n";
                    echo $counter;
                }
                $transaction = $DB->start_delegated_transaction();
                $oldgroups = $DB->get_records('offlinequiz_group', array('offlinequiz' => $offlinequiz->id), 'groupid ASC');
                $newgroups = array();
                foreach ($oldgroups as $oldgroup) {
                    $newgroup = new StdClass();
                    $newgroup->offlinequizid = $offlinequiz->id;
                    $newgroup->number = $oldgroup->groupid;
                    $newgroup->sumgrades = $oldgroup->sumgrades;
                    $newgroup->timecreated = time();
                    $newgroup->timemodified = time();
                    // First we need the ID of the new group.
                    if (!($oldid = $DB->get_field('offlinequiz_groups', 'id', array('offlinequizid' => $offlinequiz->id, 'number' => $newgroup->number)))) {
                        $newgroup->id = $DB->insert_record('offlinequiz_groups', $newgroup);
                    } else {
                        $newgroup->id = $oldid;
                    }
                    // Now create an entry in offlinquiz_group_questions for each question in the old group layout.
                    $questions = explode(',', $oldgroup->questions);
                    $position = 1;
                    foreach ($questions as $question) {
                        $groupquestion = new StdClass();
                        $groupquestion->offlinequizid = $offlinequiz->id;
                        $groupquestion->offlinegroupid = $newgroup->id;
                        $groupquestion->questionid = $question;
                        $groupquestion->position = $position++;
                        if (!$DB->get_record('offlinequiz_group_questions', array('offlinequizid' => $offlinequiz->id, 'offlinegroupid' => $newgroup->id, 'questionid' => $question))) {
                            $DB->insert_record('offlinequiz_group_questions', $groupquestion);
                        }
                    }
                    $newgroups[] = $newgroup;
                }
                require_once $CFG->dirroot . '/mod/offlinequiz/evallib.php';
                list($maxquestions, $maxanswers, $formtype, $questionsperpage) = offlinequiz_get_question_numbers($offlinequiz, $newgroups);
                foreach ($newgroups as $newgroup) {
                    // Now we know the number of pages of the group.
                    $newgroup->numberofpages = ceil($maxquestions / ($formtype * 24));
                    $DB->update_record('offlinequiz_groups', $newgroup);
                }
                $transaction->allow_commit();
            }
        }
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2012030101, 'offlinequiz');
    }
    // Migrate all entries in the offlinequiz_i_log table to the new tables offlinequiz_scanned_pages, offlinequiz_choices and.
    // Offlinequiz_page_corners. Also migrate the files to the new filesystem.
    // First we mark all offlinequizzes s.t. we upgrade them only once. Many things can go wrong here..
    if ($oldversion < 2012030200) {
        // Define field needsilogupgrade to be added to offlinequiz_attempts.
        $table = new xmldb_table('offlinequiz');
        $field = new xmldb_field('needsilogupgrade', XMLDB_TYPE_INTEGER, '3', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'timeopen');
        // Launch add field needsilogupgrade.
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }
        $DB->set_field('offlinequiz', 'needsilogupgrade', 1);
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2012030200, 'offlinequiz');
    }
    // Then we mark all offlinequiz_attempts to be upgraded.
    if ($oldversion < 2012030300) {
        // Define field needsupgradetonewqe to be added to offlinequiz_attempts.
        $table = new xmldb_table('offlinequiz_attempts');
        $field = new xmldb_field('needsupgradetonewqe', XMLDB_TYPE_INTEGER, '3', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'sheet');
        // Launch add field needsupgradetonewqe.
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }
        $DB->set_field('offlinequiz_attempts', 'needsupgradetonewqe', 1);
        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2012030300, 'offlinequiz');
    }
    // In a first step we upgrade the offlinequiz_attempts exactly like quiz_attempts (see mod/quiz/db/upgrade.php).
    if ($oldversion < 2012030400) {
        $table = new xmldb_table('question_states');
        // Echo "upgrading attempts to new question engine <br/>\n";.
        if ($dbman->table_exists($table)) {
            // NOTE: We need all attemps, also the ones with sheet=1 because the are the groups' template attempts.
            // Now update all the old attempt data.
            $oldrcachesetting = $CFG->rcache;
            $CFG->rcache = false;
            require_once $CFG->dirroot . '/mod/offlinequiz/db/upgradelib.php';
            $upgrader = new offlinequiz_attempt_upgrader();
            $upgrader->convert_all_quiz_attempts();
            $CFG->rcache = $oldrcachesetting;
        }
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2012030400, 'offlinequiz');
    }
    // Then we mark all offlinequiz_attempts to be upgraded.
    if ($oldversion < 2012030500) {
        // Define field resultid to be added to offlinequiz_attempts for later reference.
        set_time_limit(3000);
        $table = new xmldb_table('offlinequiz_attempts');
        $field = new xmldb_field('resultid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
        // Launch add field resultid.
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }
        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2012030500, 'offlinequiz');
    }
    // In a second step we convert all offlinequiz_attempts into offlinequiz_results and also upgrade the ilog table.
    if ($oldversion < 2012060101) {
        require_once $CFG->dirroot . '/mod/offlinequiz/db/upgradelib.php';
        $oldrcachesetting = $CFG->rcache;
        $CFG->rcache = false;
        $upgrader = new offlinequiz_ilog_upgrader();
        $upgrader->convert_all_offlinequiz_attempts();
        $CFG->rcache = $oldrcachesetting;
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2012060101, 'offlinequiz');
    }
    if ($oldversion < 2012060105) {
        // Changing type of field grade on table offlinequiz_q_instances to number.
        $table = new xmldb_table('offlinequiz_q_instances');
        $field = new xmldb_field('grade', XMLDB_TYPE_NUMBER, '12, 7', null, XMLDB_NOTNULL, null, '0', 'question');
        // Launch change of type for field grade.
        $dbman->change_field_type($table, $field);
        // Launch change of precision for field grade.
        $dbman->change_field_precision($table, $field);
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2012060105, 'offlinequiz');
    }
    if ($oldversion < 2012121200) {
        // Define field introformat to be added to offlinequiz.
        $table = new xmldb_table('offlinequiz');
        $field = new xmldb_field('introformat', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'intro');
        // Conditionally launch add field introformat.
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2012121200, 'offlinequiz');
    }
    if ($oldversion < 2013012400) {
        // Define field info to be added to offlinequiz_queue.
        $table = new xmldb_table('offlinequiz_queue');
        $field = new xmldb_field('info', XMLDB_TYPE_TEXT, 'medium', null, null, null, null, 'status');
        // Conditionally launch add field info.
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2013012400, 'offlinequiz');
    }
    if ($oldversion < 2013012410) {
        // Define field info to be added to offlinequiz_queue_data.
        $table = new xmldb_table('offlinequiz_queue_data');
        $field = new xmldb_field('info', XMLDB_TYPE_TEXT, 'medium', null, null, null, null, 'error');
        // Conditionally launch add field info.
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2013012410, 'offlinequiz');
    }
    if ($oldversion < 2013012500) {
        // Changing type of field grade on table offlinequiz to int.
        $table = new xmldb_table('offlinequiz');
        $field = new xmldb_field('grade', XMLDB_TYPE_NUMBER, '10, 5', null, XMLDB_NOTNULL, null, '0', 'time');
        // Launch change for field grade.
        $dbman->change_field_type($table, $field);
        $dbman->change_field_precision($table, $field);
        $dbman->change_field_unsigned($table, $field);
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2013012500, 'offlinequiz');
    }
    if ($oldversion < 2013041600) {
        // Rename field question on table offlinequiz_q_instances to questionid.
        $table = new xmldb_table('offlinequiz_q_instances');
        $field = new xmldb_field('question', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'offlinequiz');
        // Launch rename field question.
        $dbman->rename_field($table, $field, 'questionid');
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2013041600, 'offlinequiz');
    }
    if ($oldversion < 2013041601) {
        // Rename field offlinequiz on table offlinequiz_q_instances to offlinequizid.
        $table = new xmldb_table('offlinequiz_q_instances');
        $field = new xmldb_field('offlinequiz', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'id');
        // Launch rename field offlinequiz.
        $dbman->rename_field($table, $field, 'offlinequizid');
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2013041601, 'offlinequiz');
    }
    if ($oldversion < 2013061300) {
        // Define table offlinequiz_hotspots to be created.
        $table = new xmldb_table('offlinequiz_hotspots');
        // Adding fields to table offlinequiz_hotspots.
        $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
        $table->add_field('scannedpageid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
        $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
        $table->add_field('x', XMLDB_TYPE_NUMBER, '10, 2', null, XMLDB_NOTNULL, null, null);
        $table->add_field('y', XMLDB_TYPE_NUMBER, '10, 2', null, XMLDB_NOTNULL, null, null);
        $table->add_field('blank', XMLDB_TYPE_INTEGER, '1', null, null, null, null);
        $table->add_field('time', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
        // Adding keys to table offlinequiz_hotspots.
        $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
        // Adding indexes to table offlinequiz_hotspots.
        $table->add_index('scannedpageididx', XMLDB_INDEX_NOTUNIQUE, array('scannedpageid'));
        // Conditionally launch create table for offlinequiz_hotspots.
        if (!$dbman->table_exists($table)) {
            $dbman->create_table($table);
        }
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2013061300, 'offlinequiz');
    }
    if ($oldversion < 2013110800) {
        // Define field timecreated to be added to offlinequiz_queue.
        $table = new xmldb_table('offlinequiz_queue');
        $field = new xmldb_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'importuserid');
        // Conditionally launch add field timecreated.
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2013110800, 'offlinequiz');
    }
    if ($oldversion < 2013112500) {
        // Define index offlinequiz_userid_idx (not unique) to be added to offlinequiz_results.
        $table = new xmldb_table('offlinequiz_results');
        $index = new xmldb_index('offlinequiz_userid_idx', XMLDB_INDEX_NOTUNIQUE, array('userid'));
        // Conditionally launch add index offlinequiz_userid_idx.
        if (!$dbman->index_exists($table, $index)) {
            $dbman->add_index($table, $index);
        }
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2013112500, 'offlinequiz');
    }
    // Moodle v2.8.5+ release upgrade line.
    // Put any upgrade step following this.
    if ($oldversion < 2015060500) {
        // Rename field page on table offlinequiz_group_questions to NEWNAMEGOESHERE.
        $table = new xmldb_table('offlinequiz_group_questions');
        $field = new xmldb_field('pagenumber', XMLDB_TYPE_INTEGER, '4', null, null, null, null, 'position');
        // Launch rename field page.
        $dbman->rename_field($table, $field, 'page');
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2015060500, 'offlinequiz');
    }
    if ($oldversion < 2015060501) {
        // Rename field page on table offlinequiz_group_questions to NEWNAMEGOESHERE.
        $table = new xmldb_table('offlinequiz_group_questions');
        $field = new xmldb_field('usageslot', XMLDB_TYPE_INTEGER, '4', null, null, null, null, 'position');
        // Launch rename field page.
        $dbman->rename_field($table, $field, 'slot');
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2015060501, 'offlinequiz');
    }
    if ($oldversion < 2015060502) {
        // Define field maxmark to be added to offlinequiz_group_questions.
        $table = new xmldb_table('offlinequiz_group_questions');
        $field = new xmldb_field('maxmark', XMLDB_TYPE_NUMBER, '12, 7', null, XMLDB_NOTNULL, null, '1', 'slot');
        // Conditionally launch add field maxmark.
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2015060502, 'offlinequiz');
    }
    if ($oldversion < 2015060902) {
        // This upgrade migrates old offlinequiz_q_instances grades (maxgrades) to new
        // maxmark field in offlinequiz_group_questions.
        // It also deletes group questions with questionid 0 (pagebreaks) and inserts the
        // correct page number instead.
        $numofflinequizzes = $DB->count_records('offlinequiz');
        if ($numofflinequizzes > 0) {
            $pbar = new progress_bar('offlinequizquestionstoslots', 500, true);
            $pbar->create();
            $pbar->update(0, $numofflinequizzes, "Upgrading offlinequiz group questions - {0}/{$numofflinequizzes}.");
            $numberdone = 0;
            $offlinequizzes = $DB->get_recordset('offlinequiz', null, 'id', 'id, numgroups');
            foreach ($offlinequizzes as $offlinequiz) {
                $transaction = $DB->start_delegated_transaction();
                $groups = $DB->get_records('offlinequiz_groups', array('offlinequizid' => $offlinequiz->id), 'number', '*');
                $instancesraw = $DB->get_records('offlinequiz_q_instances', array('offlinequizid' => $offlinequiz->id));
                $questioninstances = array();
                foreach ($instancesraw as $instance) {
                    if (!array_key_exists($instance->questionid, $questioninstances)) {
                        $questioninstances[$instance->questionid] = $instance;
                    }
                }
                foreach ($groups as $group) {
                    $groupquestions = $DB->get_records('offlinequiz_group_questions', array('offlinequizid' => $offlinequiz->id, 'offlinegroupid' => $group->id), 'position');
                    // For every group we start on page 1.
                    $currentpage = 1;
                    $currentslot = 1;
                    foreach ($groupquestions as $groupquestion) {
                        $needsupdate = false;
                        if ($groupquestion->questionid == 0) {
                            // We remove the old pagebreaks with questionid==0.
                            $DB->delete_records('offlinequiz_group_questions', array('id' => $groupquestion->id));
                            $currentpage++;
                            continue;
                        }
                        // If the maxmarks in the question instances differs from the default maxmark (1)
                        // of the offlinequiz_group_questions then change it.
                        if (array_key_exists($groupquestion->questionid, $questioninstances) && ($maxmark = floatval($questioninstances[$groupquestion->questionid]->grade)) && abs(floatval($groupquestion->maxmark) - $maxmark) > 0.001) {
                            $groupquestion->maxmark = $maxmark;
                            $needsupdate = true;
                        }
                        // If the page number is not correct, then change it.
                        if ($groupquestion->page != $currentpage) {
                            $groupquestion->page = $currentpage;
                            $needsupdate = true;
                        }
                        // If the slot is not set, then fill it.
                        if (!$groupquestion->slot) {
                            $groupquestion->slot = $currentslot;
                            $needsupdate = true;
                        }
                        if ($needsupdate) {
                            $DB->update_record('offlinequiz_group_questions', $groupquestion);
                        }
                        $currentslot++;
                    }
                }
                // Done with this offlinequiz. Update progress bar.
                $numberdone++;
                $pbar->update($numberdone, $numofflinequizzes, "Upgrading offlinequiz group questions - {$numberdone}/{$numofflinequizzes}.");
                $transaction->allow_commit();
            }
        }
        // Offlinequiz savepoint reached.
        upgrade_mod_savepoint(true, 2015060902, 'offlinequiz');
    }
    // TODO migrate old offlinequiz_q_instances maxmarks to new maxmark field in offlinequiz_group_questions.
    // TODO migrate  offlinequiz_group_questions to fill in page field correctly. For every group use the
    //      position field to find new pages and insert them.
    //      Adapt offlinequiz code to handle missing zeros as pagebreaks.
    return true;
}
Example #4
0
        redirect($returnurl);
        break;
    case 'restore':
        if ($clist) {
            list($usql, $params) = $DB->get_in_or_equal($clist);
            $DB->set_field_select('cohort', 'component', '', 'id ' . $usql, $params);
        }
        redirect($returnurl);
        break;
    case 'delete':
        if ($clist) {
            set_time_limit(0);
            echo $OUTPUT->header();
            echo $OUTPUT->heading(get_string('auth_cohorttoolmcae', 'auth_mcae'));
            $progress = new progress_bar('delcohort');
            $progress->create();
            $delcount = count($clist);
            $delcurrent = 1;
            foreach ($clist as $cid) {
                $cohort = $DB->get_record('cohort', array('contextid' => $context->id, 'id' => $cid));
                cohort_delete_cohort($cohort);
                $progress->update($delcurrent, $delcount, "{$delcurrent} / {$delcount}");
                $delcurrent++;
            }
        }
        echo $OUTPUT->continue_button($returnurl);
        echo $OUTPUT->footer();
        die;
        break;
}
echo $OUTPUT->footer();
Example #5
0
/**
 * Quiz module upgrade function.
 * @param string $oldversion the version we are upgrading from.
 */
function xmldb_quiz_upgrade($oldversion) {
    global $CFG, $DB;

    $dbman = $DB->get_manager();

    //===== 1.9.0 upgrade line ======//

    if ($oldversion < 2008062000) {

        // Define table quiz_report to be created
        $table = new xmldb_table('quiz_report');

        // Adding fields to table quiz_report
        $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED,
                XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
        $table->add_field('name', XMLDB_TYPE_CHAR, '255', null,
                null, null, null);
        $table->add_field('displayorder', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED,
                XMLDB_NOTNULL, null, null);

        // Adding keys to table quiz_report
        $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));

        // Conditionally launch create table for quiz_report
        if (!$dbman->table_exists($table)) {
            $dbman->create_table($table);
        }

        upgrade_mod_savepoint(true, 2008062000, 'quiz');
    }

    if ($oldversion < 2008062001) {
        $reporttoinsert = new stdClass();
        $reporttoinsert->name = 'overview';
        $reporttoinsert->displayorder = 10000;
        $DB->insert_record('quiz_report', $reporttoinsert);

        $reporttoinsert = new stdClass();
        $reporttoinsert->name = 'responses';
        $reporttoinsert->displayorder = 9000;
        $DB->insert_record('quiz_report', $reporttoinsert);

        $reporttoinsert = new stdClass();
        $reporttoinsert->name = 'regrade';
        $reporttoinsert->displayorder = 7000;
        $DB->insert_record('quiz_report', $reporttoinsert);

        $reporttoinsert = new stdClass();
        $reporttoinsert->name = 'grading';
        $reporttoinsert->displayorder = 6000;
        $DB->insert_record('quiz_report', $reporttoinsert);

        upgrade_mod_savepoint(true, 2008062001, 'quiz');
    }

    if ($oldversion < 2008072402) {

        // Define field lastcron to be added to quiz_report
        $table = new xmldb_table('quiz_report');
        $field = new xmldb_field('lastcron', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED,
                XMLDB_NOTNULL, null, '0', 'displayorder');

        // Conditionally launch add field lastcron
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }

        // Define field cron to be added to quiz_report
        $field = new xmldb_field('cron', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED,
                XMLDB_NOTNULL, null, '0', 'lastcron');

        // Conditionally launch add field cron
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2008072402, 'quiz');
    }

    if ($oldversion < 2008072900) {
        // Delete the regrade report - it is now part of the overview report.
        $DB->delete_records('quiz_report', array('name' => 'regrade'));

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2008072900, 'quiz');
    }

    if ($oldversion < 2008081500) {
        // Define table quiz_question_versions to be dropped
        $table = new xmldb_table('quiz_question_versions');

        // Launch drop table for quiz_question_versions
        $dbman->drop_table($table);

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2008081500, 'quiz');
    }

    // Changing the type of all the columns that store grades to be NUMBER(10, 5) or similar.
    if ($oldversion < 2008081501) {
        // First set all quiz.sumgrades to 0 if they are null. This should never
        // happen however some users have encountered a null value there.
        $DB->execute('UPDATE {quiz} SET sumgrades=0 WHERE sumgrades IS NULL');
        $table = new xmldb_table('quiz');
        $field = new xmldb_field('sumgrades', XMLDB_TYPE_NUMBER, '10, 5', null,
                XMLDB_NOTNULL, null, '0', 'questions');
        $dbman->change_field_type($table, $field);
        upgrade_mod_savepoint(true, 2008081501, 'quiz');
    }

    if ($oldversion < 2008081502) {
        $table = new xmldb_table('quiz');
        $field = new xmldb_field('grade', XMLDB_TYPE_NUMBER, '10, 5', null,
                XMLDB_NOTNULL, null, '0', 'sumgrades');
        $dbman->change_field_type($table, $field);
        upgrade_mod_savepoint(true, 2008081502, 'quiz');
    }

    if ($oldversion < 2008081503) {
        // First set all quiz.sumgrades to 0 if they are null. This should never
        // happen however some users have encountered a null value there.
        $DB->execute('UPDATE {quiz_attempts} SET sumgrades=0 WHERE sumgrades IS NULL');
        $table = new xmldb_table('quiz_attempts');
        $field = new xmldb_field('sumgrades', XMLDB_TYPE_NUMBER, '10, 5', null,
                XMLDB_NOTNULL, null, '0', 'attempt');
        $dbman->change_field_type($table, $field);
        upgrade_mod_savepoint(true, 2008081503, 'quiz');
    }

    if ($oldversion < 2008081504) {
        $table = new xmldb_table('quiz_feedback');
        $field = new xmldb_field('mingrade', XMLDB_TYPE_NUMBER, '10, 5', null,
                XMLDB_NOTNULL, null, '0', 'feedbacktext');
        $dbman->change_field_type($table, $field);
        upgrade_mod_savepoint(true, 2008081504, 'quiz');
    }

    if ($oldversion < 2008081505) {
        $table = new xmldb_table('quiz_feedback');
        $field = new xmldb_field('maxgrade', XMLDB_TYPE_NUMBER, '10, 5', null,
                XMLDB_NOTNULL, null, '0', 'mingrade');
        $dbman->change_field_type($table, $field);
        upgrade_mod_savepoint(true, 2008081505, 'quiz');
    }

    if ($oldversion < 2008081506) {
        $table = new xmldb_table('quiz_grades');
        $field = new xmldb_field('grade', XMLDB_TYPE_NUMBER, '10, 5', null,
                XMLDB_NOTNULL, null, '0', 'userid');
        $dbman->change_field_type($table, $field);
        upgrade_mod_savepoint(true, 2008081506, 'quiz');
    }

    if ($oldversion < 2008081507) {
        $table = new xmldb_table('quiz_question_instances');
        $field = new xmldb_field('grade', XMLDB_TYPE_NUMBER, '12, 7', null,
                XMLDB_NOTNULL, null, '0', 'question');
        $dbman->change_field_type($table, $field);
        upgrade_mod_savepoint(true, 2008081507, 'quiz');
    }

    // Move all of the quiz config settings from $CFG to the config_plugins table.
    if ($oldversion < 2008082200) {
        foreach (get_object_vars($CFG) as $name => $value) {
            if (strpos($name, 'quiz_') === 0) {
                $shortname = substr($name, 5);
                if ($shortname == 'fix_adaptive') {
                    // Special case - remove old inconsistency.
                    $shortname == 'fix_optionflags';
                }
                set_config($shortname, $value, 'quiz');
                unset_config($name);
            }
        }
        upgrade_mod_savepoint(true, 2008082200, 'quiz');
    }

    // Now that the quiz is no longer responsible for creating all the question
    // bank tables, and some of the tables are now the responsibility of the
    // datasetdependent question type, which did not have a version.php file before,
    // we need to say that these tables are already installed, otherwise XMLDB
    // will try to create them again and give an error.
    if ($oldversion < 2008082600) {
        // Since MDL-16505 was fixed, and we eliminated the datasetdependent
        // question type, this is now a no-op.
        upgrade_mod_savepoint(true, 2008082600, 'quiz');
    }

    if ($oldversion < 2008112101) {

        // Define field lastcron to be added to quiz_report
        $table = new xmldb_table('quiz_report');
        $field = new xmldb_field('capability', XMLDB_TYPE_CHAR, '255', null,
                null, null, null, 'cron');

        // Conditionally launch add field lastcron
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2008112101, 'quiz');
    }

    if ($oldversion < 2009010700) {

        // Define field showuserpicture to be added to quiz
        $table = new xmldb_table('quiz');
        $field = new xmldb_field('showuserpicture', XMLDB_TYPE_INTEGER, '4', null,
                XMLDB_NOTNULL, null, '0', 'delay2');

        // Conditionally launch add field showuserpicture
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2009010700, 'quiz');
    }

    if ($oldversion < 2009030900) {
        // If there are no quiz settings set to advanced yet, the set up the default
        // advanced fields from Moodle 2.0.
        $quizconfig = get_config('quiz');
        $arealreadyadvanced = false;
        foreach (array($quizconfig) as $name => $value) {
            if (strpos($name, 'fix_') === 0 && !empty($value)) {
                $arealreadyadvanced = true;
                break;
            }
        }

        if (!$arealreadyadvanced) {
            set_config('fix_penaltyscheme', 1, 'quiz');
            set_config('fix_attemptonlast', 1, 'quiz');
            set_config('fix_questiondecimalpoints', 1, 'quiz');
            set_config('fix_password', 1, 'quiz');
            set_config('fix_subnet', 1, 'quiz');
            set_config('fix_delay1', 1, 'quiz');
            set_config('fix_delay2', 1, 'quiz');
            set_config('fix_popup', 1, 'quiz');
        }

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2009030900, 'quiz');
    }

    if ($oldversion < 2009031000) {
        // Add new questiondecimaldigits setting, separate form the overall decimaldigits one.
        $table = new xmldb_table('quiz');
        $field = new xmldb_field('questiondecimalpoints', XMLDB_TYPE_INTEGER, '4', null,
                XMLDB_NOTNULL, null, '-2', 'decimalpoints');
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2009031000, 'quiz');
    }

    if ($oldversion < 2009031001) {
        // Convert quiz.timelimit from minutes to seconds.
        $DB->execute('UPDATE {quiz} SET timelimit = timelimit * 60');
        $default = get_config('quiz', 'timelimit');
        set_config('timelimit', 60 * $default, 'quiz');

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2009031001, 'quiz');
    }

    if ($oldversion < 2009042000) {

        // Define field introformat to be added to quiz
        $table = new xmldb_table('quiz');
        $field = new xmldb_field('introformat', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED,
                XMLDB_NOTNULL, null, '0', 'intro');

        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }

        // conditionally migrate to html format in intro
        if ($CFG->texteditors !== 'textarea') {
            $rs = $DB->get_recordset('quiz', array('introformat' => FORMAT_MOODLE),
                    '', 'id, intro, introformat');
            foreach ($rs as $q) {
                $q->intro       = text_to_html($q->intro, false, false, true);
                $q->introformat = FORMAT_HTML;
                $DB->update_record('quiz', $q);
                upgrade_set_timeout();
            }
            $rs->close();
        }

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2009042000, 'quiz');
    }

    if ($oldversion < 2010030501) {
        // Define table quiz_overrides to be created
        $table = new xmldb_table('quiz_overrides');

        // Adding fields to table quiz_overrides
        $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED,
                XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
        $table->add_field('quiz', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED,
                XMLDB_NOTNULL, null, '0');
        $table->add_field('groupid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED,
                null, null, null);
        $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED,
                null, null, null);
        $table->add_field('timeopen', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED,
                null, null, null);
        $table->add_field('timeclose', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED,
                null, null, null);
        $table->add_field('timelimit', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED,
                null, null, null);
        $table->add_field('attempts', XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED,
                null, null, null);
        $table->add_field('password', XMLDB_TYPE_CHAR, '255', null, null, null, null);

        // Adding keys to table quiz_overrides
        $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
        $table->add_key('quiz', XMLDB_KEY_FOREIGN, array('quiz'), 'quiz', array('id'));
        $table->add_key('groupid', XMLDB_KEY_FOREIGN, array('groupid'), 'groups', array('id'));
        $table->add_key('userid', XMLDB_KEY_FOREIGN, array('userid'), 'user', array('id'));

        // Conditionally launch create table for quiz_overrides
        if (!$dbman->table_exists($table)) {
            $dbman->create_table($table);
        }

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2010030501, 'quiz');
    }

    if ($oldversion < 2010051800) {

        // Define field showblocks to be added to quiz
        $table = new xmldb_table('quiz');
        $field = new xmldb_field('showblocks', XMLDB_TYPE_INTEGER, '4', null,
                XMLDB_NOTNULL, null, '0', 'showuserpicture');

        // Conditionally launch add field showblocks
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2010051800, 'quiz');
    }

    if ($oldversion < 2010080600) {

        // Define field feedbacktextformat to be added to quiz_feedback
        $table = new xmldb_table('quiz_feedback');
        $field = new xmldb_field('feedbacktextformat', XMLDB_TYPE_INTEGER, '2', null,
                XMLDB_NOTNULL, null, '0', 'feedbacktext');

        // Conditionally launch add field feedbacktextformat
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }

        // This column defaults to FORMAT_MOODLE, which is correct.

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2010080600, 'quiz');
    }

    if ($oldversion < 2010102000) {

        // Define field showblocks to be added to quiz
        // Repeat this step, because the column was missing from install.xml for a time.
        $table = new xmldb_table('quiz');
        $field = new xmldb_field('showblocks', XMLDB_TYPE_INTEGER, '4', null,
                XMLDB_NOTNULL, null, '0', 'showuserpicture');

        // Conditionally launch add field showblocks
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2010102000, 'quiz');
    }

    if ($oldversion < 2010122300) {
        // Fix quiz in the post table after upgrade from 1.9
        $table = new xmldb_table('quiz');
        $columns = $DB->get_columns('quiz');

        // quiz.questiondecimalpoints should be int (4) not null default -2
        if (array_key_exists('questiondecimalpoints', $columns) &&
                $columns['questiondecimalpoints']->default_value != '-2') {
            $field = new xmldb_field('questiondecimalpoints', XMLDB_TYPE_INTEGER, '4', null,
                    XMLDB_NOTNULL, null, -2, 'decimalpoints');
            if ($dbman->field_exists($table, $field)) {
                $dbman->change_field_default($table, $field);
            }
        }

        // quiz.sumgrades should be decimal(10, 5) not null default 0
        if (array_key_exists('sumgrades', $columns) && empty($columns['sumgrades']->not_null)) {
            // First set all quiz.sumgrades to 0 if they are null. This should never
            // happen however some users have encountered a null value there.
            $DB->execute('UPDATE {quiz} SET sumgrades=0 WHERE sumgrades IS NULL');

            $field = new xmldb_field('sumgrades', XMLDB_TYPE_NUMBER, '10, 5', null,
                    XMLDB_NOTNULL, null, '0', 'questions');
            if ($dbman->field_exists($table, $field)) {
                $dbman->change_field_default($table, $field);
            }
        }

        // quiz.grade should be decimal(10, 5) not null default 0
        if (array_key_exists('grade', $columns) && empty($columns['grade']->not_null)) {
            $field = new xmldb_field('grade', XMLDB_TYPE_NUMBER, '10, 5', null,
                    XMLDB_NOTNULL, null, '0', 'sumgrades');
            if ($dbman->field_exists($table, $field)) {
                $dbman->change_field_default($table, $field);
            }
        }

        upgrade_mod_savepoint(true, 2010122300, 'quiz');
    }

    if ($oldversion < 2010122301) {
        // Fix quiz_attempts in the post table after upgrade from 1.9
        $table = new xmldb_table('quiz_attempts');
        $columns = $DB->get_columns('quiz_attempts');

        // quiz_attempts.sumgrades should be decimal(10, 5) not null default 0
        if (array_key_exists('sumgrades', $columns) && empty($columns['sumgrades']->not_null)) {
            // First set all quiz.sumgrades to 0 if they are null. This should never
            // happen however some users have encountered a null value there.
            $DB->execute('UPDATE {quiz_attempts} SET sumgrades=0 WHERE sumgrades IS NULL');

            $field = new xmldb_field('sumgrades', XMLDB_TYPE_NUMBER, '10, 5', null,
                    XMLDB_NOTNULL, null, '0', 'attempt');
            if ($dbman->field_exists($table, $field)) {
                $dbman->change_field_default($table, $field);
            }
        }

        upgrade_mod_savepoint(true, 2010122301, 'quiz');
    }

    if ($oldversion < 2010122302) {
        // Fix quiz_feedback in the post table after upgrade from 1.9
        $table = new xmldb_table('quiz_feedback');
        $columns = $DB->get_columns('quiz_feedback');

        // quiz_feedback.mingrade should be decimal(10, 5) not null default 0
        if (array_key_exists('mingrade', $columns) && empty($columns['mingrade']->not_null)) {
            $field = new xmldb_field('mingrade', XMLDB_TYPE_NUMBER, '10, 5', null,
                    XMLDB_NOTNULL, null, '0', 'feedbacktextformat');
            if ($dbman->field_exists($table, $field)) {
                $dbman->change_field_default($table, $field);
            }
        }

        // quiz_feedback.maxgrade should be decimal(10, 5) not null default 0
        if (array_key_exists('maxgrade', $columns) && empty($columns['maxgrade']->not_null)) {
            // Fixed in earlier upgrade code
            $field = new xmldb_field('maxgrade', XMLDB_TYPE_NUMBER, '10, 5', null,
                    XMLDB_NOTNULL, null, '0', 'mingrade');
            if ($dbman->field_exists($table, $field)) {
                $dbman->change_field_default($table, $field);
            }
        }

        upgrade_mod_savepoint(true, 2010122302, 'quiz');
    }

    if ($oldversion < 2010122303) {
        // Fix quiz_grades in the post table after upgrade from 1.9
        $table = new xmldb_table('quiz_grades');
        $columns = $DB->get_columns('quiz_grades');

        // quiz_grades.grade should be decimal(10, 5) not null default 0
        if (array_key_exists('grade', $columns) && empty($columns['grade']->not_null)) {
            $field = new xmldb_field('grade', XMLDB_TYPE_NUMBER, '10, 5', null,
                    XMLDB_NOTNULL, null, '0', 'userid');
            if ($dbman->field_exists($table, $field)) {
                $dbman->change_field_default($table, $field);
            }
        }

        upgrade_mod_savepoint(true, 2010122303, 'quiz');
    }

    if ($oldversion < 2010122304) {
        // Fix quiz_question_instances in the post table after upgrade from 1.9
        $table = new xmldb_table('quiz_question_instances');
        $columns = $DB->get_columns('quiz_question_instances');

        // quiz_question_instances.grade should be decimal(12, 7) not null default 0
        if (array_key_exists('grade', $columns) && empty($columns['grade']->not_null)) {
            $field = new xmldb_field('grade', XMLDB_TYPE_NUMBER, '12, 7', null,
                    XMLDB_NOTNULL, null, '0', 'question');
            if ($dbman->field_exists($table, $field)) {
                $dbman->change_field_default($table, $field);
            }
        }

        upgrade_mod_savepoint(true, 2010122304, 'quiz');
    }

    //===== 2.1.0 upgrade line ======//

    // Complete any old upgrade from 1.5 that was never finished.
    if ($oldversion < 2011051199) {
        $table = new xmldb_table('question_states');
        if ($dbman->table_exists($table)) {
            $transaction = $DB->start_delegated_transaction();

            $oldattempts = $DB->get_records_sql('
                SELECT *
                  FROM {quiz_attempts} quiza
                 WHERE uniqueid IN (
                    SELECT DISTINCT qst.attempt
                      FROM {question_states} qst
                      LEFT JOIN {question_sessions} qsess ON
                            qst.question = qsess.questionid AND qst.attempt = qsess.attemptid
                     WHERE qsess.id IS NULL
                )
            ');

            if ($oldattempts) {
                require_once($CFG->dirroot . '/mod/quiz/db/upgradelib.php');

                $pbar = new progress_bar('q15upgrade');
                $pbar->create();
                $a = new stdClass();
                $a->outof = count($oldattempts);
                $a->done = 0;
                $pbar->update($a->done, $a->outof,
                        get_string('upgradingveryoldquizattempts', 'quiz', $a));

                foreach ($oldattempts as $oldattempt) {
                    quiz_upgrade_very_old_question_sessions($oldattempt);

                    $a->done += 1;
                    $pbar->update($a->done, $a->outof,
                            get_string('upgradingveryoldquizattempts', 'quiz', $a));
                }
            }

            $transaction->allow_commit();
        }

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2011051199, 'quiz');
    }

    // Add new preferredbehaviour column to the quiz table.
    if ($oldversion < 2011051200) {
        $table = new xmldb_table('quiz');
        $field = new xmldb_field('preferredbehaviour');
        $field->set_attributes(XMLDB_TYPE_CHAR, '32', null,
                null, null, null, 'timeclose');
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2011051200, 'quiz');
    }

    // Populate preferredbehaviour column based on old optionflags column.
    if ($oldversion < 2011051201) {
        if ($dbman->field_exists('quiz', 'optionflags')) {
            $DB->set_field_select('quiz', 'preferredbehaviour', 'deferredfeedback',
                    'optionflags = 0');
            $DB->set_field_select('quiz', 'preferredbehaviour', 'adaptive',
                    'optionflags <> 0 AND penaltyscheme <> 0');
            $DB->set_field_select('quiz', 'preferredbehaviour', 'adaptivenopenalty',
                    'optionflags <> 0 AND penaltyscheme = 0');

            set_config('preferredbehaviour', 'deferredfeedback', 'quiz');
            set_config('fix_preferredbehaviour', 0, 'quiz');
        }

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2011051201, 'quiz');
    }

    // Add a not-NULL constraint to the preferredmodel field now that it is populated.
    if ($oldversion < 2011051202) {
        $table = new xmldb_table('quiz');
        $field = new xmldb_field('preferredbehaviour');
        $field->set_attributes(XMLDB_TYPE_CHAR, '32', null,
                XMLDB_NOTNULL, null, null, 'timeclose');

        $dbman->change_field_notnull($table, $field);

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2011051202, 'quiz');
    }

    // Drop the old optionflags field.
    if ($oldversion < 2011051203) {
        $table = new xmldb_table('quiz');
        $field = new xmldb_field('optionflags');

        if ($dbman->field_exists($table, $field)) {
            $dbman->drop_field($table, $field);
        }

        unset_config('optionflags', 'quiz');
        unset_config('fix_optionflags', 'quiz');

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2011051203, 'quiz');
    }

    // Drop the old penaltyscheme field.
    if ($oldversion < 2011051204) {
        $table = new xmldb_table('quiz');
        $field = new xmldb_field('penaltyscheme');

        if ($dbman->field_exists($table, $field)) {
            $dbman->drop_field($table, $field);
        }

        unset_config('penaltyscheme', 'quiz');
        unset_config('fix_penaltyscheme', 'quiz');

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2011051204, 'quiz');
    }

    if ($oldversion < 2011051205) {

        // Changing nullability of field sumgrades on table quiz_attempts to null
        $table = new xmldb_table('quiz_attempts');
        $field = new xmldb_field('sumgrades');
        $field->set_attributes(XMLDB_TYPE_NUMBER, '10, 5', null,
                null, null, null, 'attempt');

        // Launch change of nullability for field sumgrades
        $dbman->change_field_notnull($table, $field);

        // Launch change of default for field sumgrades
        $dbman->change_field_default($table, $field);

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2011051205, 'quiz');
    }

    if ($oldversion < 2011051207) {

        // Define field reviewattempt to be added to quiz
        $table = new xmldb_table('quiz');
        $field = new xmldb_field('reviewattempt');
        $field->set_attributes(XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED,
                XMLDB_NOTNULL, null, '0', 'review');

        // Launch add field reviewattempt
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2011051207, 'quiz');
    }

    if ($oldversion < 2011051208) {

        // Define field reviewattempt to be added to quiz
        $table = new xmldb_table('quiz');
        $field = new xmldb_field('reviewcorrectness');
        $field->set_attributes(XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED,
                XMLDB_NOTNULL, null, '0', 'reviewattempt');

        // Launch add field reviewattempt
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2011051208, 'quiz');
    }

    if ($oldversion < 2011051209) {

        // Define field reviewattempt to be added to quiz
        $table = new xmldb_table('quiz');
        $field = new xmldb_field('reviewmarks');
        $field->set_attributes(XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED,
                XMLDB_NOTNULL, null, '0', 'reviewcorrectness');

        // Launch add field reviewattempt
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2011051209, 'quiz');
    }

    if ($oldversion < 2011051210) {

        // Define field reviewattempt to be added to quiz
        $table = new xmldb_table('quiz');
        $field = new xmldb_field('reviewspecificfeedback');
        $field->set_attributes(XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED,
                XMLDB_NOTNULL, null, '0', 'reviewmarks');

        // Launch add field reviewattempt
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2011051210, 'quiz');
    }

    if ($oldversion < 2011051211) {

        // Define field reviewattempt to be added to quiz
        $table = new xmldb_table('quiz');
        $field = new xmldb_field('reviewgeneralfeedback');
        $field->set_attributes(XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED,
                XMLDB_NOTNULL, null, '0', 'reviewspecificfeedback');

        // Launch add field reviewattempt
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2011051211, 'quiz');
    }

    if ($oldversion < 2011051212) {

        // Define field reviewattempt to be added to quiz
        $table = new xmldb_table('quiz');
        $field = new xmldb_field('reviewrightanswer');
        $field->set_attributes(XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED,
                XMLDB_NOTNULL, null, '0', 'reviewgeneralfeedback');

        // Launch add field reviewattempt
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2011051212, 'quiz');
    }

    if ($oldversion < 2011051213) {

        // Define field reviewattempt to be added to quiz
        $table = new xmldb_table('quiz');
        $field = new xmldb_field('reviewoverallfeedback');
        $field->set_attributes(XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED,
                XMLDB_NOTNULL, null, '0', 'reviewrightanswer');

        // Launch add field reviewattempt
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2011051213, 'quiz');
    }

    define('QUIZ_NEW_DURING',            0x10000);
    define('QUIZ_NEW_IMMEDIATELY_AFTER', 0x01000);
    define('QUIZ_NEW_LATER_WHILE_OPEN',  0x00100);
    define('QUIZ_NEW_AFTER_CLOSE',       0x00010);

    define('QUIZ_OLD_IMMEDIATELY', 0x3c003f);
    define('QUIZ_OLD_OPEN',        0x3c00fc0);
    define('QUIZ_OLD_CLOSED',      0x3c03f000);

    define('QUIZ_OLD_RESPONSES',        1*0x1041); // Show responses
    define('QUIZ_OLD_SCORES',           2*0x1041); // Show scores
    define('QUIZ_OLD_FEEDBACK',         4*0x1041); // Show question feedback
    define('QUIZ_OLD_ANSWERS',          8*0x1041); // Show correct answers
    define('QUIZ_OLD_SOLUTIONS',       16*0x1041); // Show solutions
    define('QUIZ_OLD_GENERALFEEDBACK', 32*0x1041); // Show question general feedback
    define('QUIZ_OLD_OVERALLFEEDBACK',  1*0x4440000); // Show quiz overall feedback

    // Copy the old review settings
    if ($oldversion < 2011051214) {
        if ($dbman->field_exists('quiz', 'review')) {
            $DB->execute("
            UPDATE {quiz}
            SET reviewattempt = " . $DB->sql_bitor($DB->sql_bitor(
                QUIZ_NEW_DURING,
                'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_RESPONSES) .
                    ' <> 0 THEN ' . QUIZ_NEW_IMMEDIATELY_AFTER . ' ELSE 0 END'), $DB->sql_bitor(
                'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_OPEN & QUIZ_OLD_RESPONSES) .
                    ' <> 0 THEN ' . QUIZ_NEW_LATER_WHILE_OPEN . ' ELSE 0 END',
                'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_CLOSED & QUIZ_OLD_RESPONSES) .
                    ' <> 0 THEN ' . QUIZ_NEW_AFTER_CLOSE . ' ELSE 0 END')) . "
            ");
        }

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2011051214, 'quiz');
    }

    if ($oldversion < 2011051215) {
        if ($dbman->field_exists('quiz', 'review')) {
            $DB->execute("
            UPDATE {quiz}
            SET reviewcorrectness = " . $DB->sql_bitor($DB->sql_bitor(
                QUIZ_NEW_DURING,
                'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_SCORES) .
                    ' <> 0 THEN ' . QUIZ_NEW_IMMEDIATELY_AFTER . ' ELSE 0 END'), $DB->sql_bitor(
                'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_OPEN & QUIZ_OLD_SCORES) .
                    ' <> 0 THEN ' . QUIZ_NEW_LATER_WHILE_OPEN . ' ELSE 0 END',
                'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_CLOSED & QUIZ_OLD_SCORES) .
                    ' <> 0 THEN ' . QUIZ_NEW_AFTER_CLOSE . ' ELSE 0 END')) . "
            ");
        }

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2011051215, 'quiz');
    }

    if ($oldversion < 2011051216) {
        if ($dbman->field_exists('quiz', 'review')) {
            $DB->execute("
            UPDATE {quiz}
            SET reviewmarks = " . $DB->sql_bitor($DB->sql_bitor(
                QUIZ_NEW_DURING,
                'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_SCORES) .
                    ' <> 0 THEN ' . QUIZ_NEW_IMMEDIATELY_AFTER . ' ELSE 0 END'), $DB->sql_bitor(
                'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_OPEN & QUIZ_OLD_SCORES) .
                    ' <> 0 THEN ' . QUIZ_NEW_LATER_WHILE_OPEN . ' ELSE 0 END',
                'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_CLOSED & QUIZ_OLD_SCORES) .
                    ' <> 0 THEN ' . QUIZ_NEW_AFTER_CLOSE . ' ELSE 0 END')) . "
            ");
        }

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2011051216, 'quiz');
    }

    if ($oldversion < 2011051217) {
        if ($dbman->field_exists('quiz', 'review')) {
            $DB->execute("
            UPDATE {quiz}
            SET reviewspecificfeedback = " . $DB->sql_bitor($DB->sql_bitor(
                'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_FEEDBACK) .
                    ' <> 0 THEN ' . QUIZ_NEW_DURING . ' ELSE 0 END',
                'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_FEEDBACK) .
                    ' <> 0 THEN ' . QUIZ_NEW_IMMEDIATELY_AFTER . ' ELSE 0 END'), $DB->sql_bitor(
                'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_OPEN & QUIZ_OLD_FEEDBACK) .
                    ' <> 0 THEN ' . QUIZ_NEW_LATER_WHILE_OPEN . ' ELSE 0 END',
                'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_CLOSED & QUIZ_OLD_FEEDBACK) .
                    ' <> 0 THEN ' . QUIZ_NEW_AFTER_CLOSE . ' ELSE 0 END')) . "
            ");
        }

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2011051217, 'quiz');
    }

    if ($oldversion < 2011051218) {
        if ($dbman->field_exists('quiz', 'review')) {
            $DB->execute("
            UPDATE {quiz}
            SET reviewgeneralfeedback = " . $DB->sql_bitor($DB->sql_bitor(
                'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_GENERALFEEDBACK) .
                    ' <> 0 THEN ' . QUIZ_NEW_DURING . ' ELSE 0 END',
                'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_GENERALFEEDBACK) .
                    ' <> 0 THEN ' . QUIZ_NEW_IMMEDIATELY_AFTER . ' ELSE 0 END'), $DB->sql_bitor(
                'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_OPEN & QUIZ_OLD_GENERALFEEDBACK) .
                    ' <> 0 THEN ' . QUIZ_NEW_LATER_WHILE_OPEN . ' ELSE 0 END',
                'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_CLOSED & QUIZ_OLD_GENERALFEEDBACK) .
                    ' <> 0 THEN ' . QUIZ_NEW_AFTER_CLOSE . ' ELSE 0 END')) . "
            ");
        }

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2011051218, 'quiz');
    }

    if ($oldversion < 2011051219) {
        if ($dbman->field_exists('quiz', 'review')) {
            $DB->execute("
            UPDATE {quiz}
            SET reviewrightanswer = " . $DB->sql_bitor($DB->sql_bitor(
                'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_ANSWERS) .
                    ' <> 0 THEN ' . QUIZ_NEW_DURING . ' ELSE 0 END',
                'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_ANSWERS) .
                    ' <> 0 THEN ' . QUIZ_NEW_IMMEDIATELY_AFTER . ' ELSE 0 END'), $DB->sql_bitor(
                'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_OPEN & QUIZ_OLD_ANSWERS) .
                    ' <> 0 THEN ' . QUIZ_NEW_LATER_WHILE_OPEN . ' ELSE 0 END',
                'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_CLOSED & QUIZ_OLD_ANSWERS) .
                    ' <> 0 THEN ' . QUIZ_NEW_AFTER_CLOSE . ' ELSE 0 END')) . "
            ");
        }

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2011051219, 'quiz');
    }

    if ($oldversion < 2011051220) {
        if ($dbman->field_exists('quiz', 'review')) {
            $DB->execute("
            UPDATE {quiz}
            SET reviewoverallfeedback = " . $DB->sql_bitor($DB->sql_bitor(
                0,
                'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_OVERALLFEEDBACK) .
                    ' <> 0 THEN ' . QUIZ_NEW_IMMEDIATELY_AFTER . ' ELSE 0 END'), $DB->sql_bitor(
                'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_OPEN & QUIZ_OLD_OVERALLFEEDBACK) .
                    ' <> 0 THEN ' . QUIZ_NEW_LATER_WHILE_OPEN . ' ELSE 0 END',
                'CASE WHEN ' . $DB->sql_bitand('review', QUIZ_OLD_CLOSED & QUIZ_OLD_OVERALLFEEDBACK) .
                    ' <> 0 THEN ' . QUIZ_NEW_AFTER_CLOSE . ' ELSE 0 END')) . "
            ");
        }

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2011051220, 'quiz');
    }

    // And, do the same for the defaults
    if ($oldversion < 2011051221) {
        $quizrevew = get_config('quiz', 'review');
        if (!empty($quizrevew)) {

            set_config('reviewattempt',
                    QUIZ_NEW_DURING |
                    ($quizrevew & QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_RESPONSES ? QUIZ_NEW_IMMEDIATELY_AFTER : 0) |
                    ($quizrevew & QUIZ_OLD_OPEN & QUIZ_OLD_RESPONSES ? QUIZ_NEW_LATER_WHILE_OPEN : 0) |
                    ($quizrevew & QUIZ_OLD_CLOSED & QUIZ_OLD_RESPONSES ? QUIZ_NEW_AFTER_CLOSE : 0),
                    'quiz');

            set_config('reviewcorrectness',
                    QUIZ_NEW_DURING |
                    ($quizrevew & QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_SCORES ? QUIZ_NEW_IMMEDIATELY_AFTER : 0) |
                    ($quizrevew & QUIZ_OLD_OPEN & QUIZ_OLD_SCORES ? QUIZ_NEW_LATER_WHILE_OPEN : 0) |
                    ($quizrevew & QUIZ_OLD_CLOSED & QUIZ_OLD_SCORES ? QUIZ_NEW_AFTER_CLOSE : 0),
                    'quiz');

            set_config('reviewmarks',
                    QUIZ_NEW_DURING |
                    ($quizrevew & QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_SCORES ? QUIZ_NEW_IMMEDIATELY_AFTER : 0) |
                    ($quizrevew & QUIZ_OLD_OPEN & QUIZ_OLD_SCORES ? QUIZ_NEW_LATER_WHILE_OPEN : 0) |
                    ($quizrevew & QUIZ_OLD_CLOSED & QUIZ_OLD_SCORES ? QUIZ_NEW_AFTER_CLOSE : 0),
                    'quiz');

            set_config('reviewspecificfeedback',
                    ($quizrevew & QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_FEEDBACK ? QUIZ_NEW_DURING : 0) |
                    ($quizrevew & QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_FEEDBACK ? QUIZ_NEW_IMMEDIATELY_AFTER : 0) |
                    ($quizrevew & QUIZ_OLD_OPEN & QUIZ_OLD_FEEDBACK ? QUIZ_NEW_LATER_WHILE_OPEN : 0) |
                    ($quizrevew & QUIZ_OLD_CLOSED & QUIZ_OLD_FEEDBACK ? QUIZ_NEW_AFTER_CLOSE : 0),
                    'quiz');

            set_config('reviewgeneralfeedback',
                    ($quizrevew & QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_GENERALFEEDBACK ? QUIZ_NEW_DURING : 0) |
                    ($quizrevew & QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_GENERALFEEDBACK ? QUIZ_NEW_IMMEDIATELY_AFTER : 0) |
                    ($quizrevew & QUIZ_OLD_OPEN & QUIZ_OLD_GENERALFEEDBACK ? QUIZ_NEW_LATER_WHILE_OPEN : 0) |
                    ($quizrevew & QUIZ_OLD_CLOSED & QUIZ_OLD_GENERALFEEDBACK ? QUIZ_NEW_AFTER_CLOSE : 0),
                    'quiz');

            set_config('reviewrightanswer',
                    ($quizrevew & QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_ANSWERS ? QUIZ_NEW_DURING : 0) |
                    ($quizrevew & QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_ANSWERS ? QUIZ_NEW_IMMEDIATELY_AFTER : 0) |
                    ($quizrevew & QUIZ_OLD_OPEN & QUIZ_OLD_ANSWERS ? QUIZ_NEW_LATER_WHILE_OPEN : 0) |
                    ($quizrevew & QUIZ_OLD_CLOSED & QUIZ_OLD_ANSWERS ? QUIZ_NEW_AFTER_CLOSE : 0),
                    'quiz');

            set_config('reviewoverallfeedback',
                    0 |
                    ($quizrevew & QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_OVERALLFEEDBACK ? QUIZ_NEW_IMMEDIATELY_AFTER : 0) |
                    ($quizrevew & QUIZ_OLD_OPEN & QUIZ_OLD_OVERALLFEEDBACK ? QUIZ_NEW_LATER_WHILE_OPEN : 0) |
                    ($quizrevew & QUIZ_OLD_CLOSED & QUIZ_OLD_OVERALLFEEDBACK ? QUIZ_NEW_AFTER_CLOSE : 0),
                    'quiz');
        }

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2011051221, 'quiz');
    }

    // Finally drop the old column
    if ($oldversion < 2011051222) {
        // Define field review to be dropped from quiz
        $table = new xmldb_table('quiz');
        $field = new xmldb_field('review');

        // Launch drop field review
        if ($dbman->field_exists($table, $field)) {
            $dbman->drop_field($table, $field);
        }

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2011051222, 'quiz');
    }

    if ($oldversion < 2011051223) {
        unset_config('review', 'quiz');

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2011051223, 'quiz');
    }

    if ($oldversion < 2011051225) {
        // Define table quiz_report to be renamed to quiz_reports
        $table = new xmldb_table('quiz_report');

        // Launch rename table for quiz_reports
        if ($dbman->table_exists($table)) {
            $dbman->rename_table($table, 'quiz_reports');
        }

        upgrade_mod_savepoint(true, 2011051225, 'quiz');
    }

    if ($oldversion < 2011051226) {
        // Define index name (unique) to be added to quiz_reports
        $table = new xmldb_table('quiz_reports');
        $index = new xmldb_index('name', XMLDB_INDEX_UNIQUE, array('name'));

        // Conditionally launch add index name
        if (!$dbman->index_exists($table, $index)) {
            $dbman->add_index($table, $index);
        }

        upgrade_mod_savepoint(true, 2011051226, 'quiz');
    }

    if ($oldversion < 2011051227) {

        // Changing nullability of field sumgrades on table quiz_attempts to null
        $table = new xmldb_table('quiz_attempts');
        $field = new xmldb_field('sumgrades', XMLDB_TYPE_NUMBER, '10, 5', null,
                null, null, null, 'attempt');

        // Launch change of nullability for field sumgrades
        $dbman->change_field_notnull($table, $field);

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2011051227, 'quiz');
    }

    if ($oldversion < 2011051228) {
        // Define field needsupgradetonewqe to be added to quiz_attempts
        $table = new xmldb_table('quiz_attempts');
        $field = new xmldb_field('needsupgradetonewqe', XMLDB_TYPE_INTEGER, '3', XMLDB_UNSIGNED,
                XMLDB_NOTNULL, null, '0', 'preview');

        // Launch add field needsupgradetonewqe
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }

        $DB->set_field('quiz_attempts', 'needsupgradetonewqe', 1);

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2011051228, 'quiz');
    }

    if ($oldversion < 2011051229) {
        $table = new xmldb_table('question_states');
        if ($dbman->table_exists($table)) {
            // First delete all data from preview attempts.
            $DB->delete_records_select('question_states',
                    "attempt IN (SELECT uniqueid FROM {quiz_attempts} WHERE preview = 1)");
            $DB->delete_records_select('question_sessions',
                    "attemptid IN (SELECT uniqueid FROM {quiz_attempts} WHERE preview = 1)");
            $DB->delete_records('quiz_attempts', array('preview' => 1));

            // Now update all the old attempt data.
            $oldrcachesetting = $CFG->rcache;
            $CFG->rcache = false;

            require_once($CFG->dirroot . '/question/engine/upgrade/upgradelib.php');
            $upgrader = new question_engine_attempt_upgrader();
            $upgrader->convert_all_quiz_attempts();

            $CFG->rcache = $oldrcachesetting;
        }

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2011051229, 'quiz');
    }

    // Moodle v2.1.0 release upgrade line
    // Put any upgrade step following this

    if ($oldversion < 2011100600) {

        // Define field browsersecurity to be added to quiz
        $table = new xmldb_table('quiz');
        $field = new xmldb_field('browsersecurity', XMLDB_TYPE_CHAR, '32', null,
                XMLDB_NOTNULL, null, '[unknownvalue]', 'subnet');

        // Conditionally launch add field browsersecurity
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2011100600, 'quiz');
    }

    if ($oldversion < 2011100601) {
        $DB->set_field('quiz', 'browsersecurity', '-', array('popup' => 0));
        $DB->set_field('quiz', 'browsersecurity', 'securewindow', array('popup' => 1));
        $DB->set_field('quiz', 'browsersecurity', 'safebrowser', array('popup' => 2));

        upgrade_mod_savepoint(true, 2011100601, 'quiz');
    }

    if ($oldversion < 2011100602) {

        // Changing the default of field browsersecurity on table quiz to drop it
        $table = new xmldb_table('quiz');
        $field = new xmldb_field('browsersecurity', XMLDB_TYPE_CHAR, '32', null,
                XMLDB_NOTNULL, null, null, 'subnet');

        // Launch change of default for field browsersecurity
        $dbman->change_field_default($table, $field);

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2011100602, 'quiz');
    }

    if ($oldversion < 2011100603) {

        // Define field popup to be dropped from quiz
        $table = new xmldb_table('quiz');
        $field = new xmldb_field('popup');

        // Conditionally launch drop field popup
        if ($dbman->field_exists($table, $field)) {
            $dbman->drop_field($table, $field);
        }

        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2011100603, 'quiz');
    }

    if ($oldversion < 2011100604) {
        switch (get_config('quiz', 'popup')) {
            case 1:
                set_config('browsersecurity', 'securewindow', 'quiz');
                break;
            case 2:
                set_config('browsersecurity', 'safebrowser', 'quiz');
                break;
            default:
                set_config('browsersecurity', '-', 'quiz');
        }
        unset_config('quiz', 'popup');

        set_config('browsersecurity_adv', get_config('quiz', 'popup_adv'), 'quiz');
        unset_config('quiz', 'popup_adv');

        upgrade_mod_savepoint(true, 2011100604, 'quiz');
    }

    // Moodle v2.2.0 release upgrade line
    // Put any upgrade step following this

    return true;
}
Example #6
0
admin_externalpage_setup('toolcustomlang');
$langs = get_string_manager()->get_list_of_translations();
// pre-output actions
if ($action === 'checkout') {
    require_sesskey();
    require_capability('tool/customlang:edit', context_system::instance());
    if (empty($lng)) {
        print_error('missingparameter');
    }
    $PAGE->set_cacheable(false);
    // progress bar is used here
    $output = $PAGE->get_renderer('tool_customlang');
    echo $output->header();
    echo $output->heading(get_string('pluginname', 'tool_customlang'));
    $progressbar = new progress_bar();
    $progressbar->create();
    // prints the HTML code of the progress bar
    // we may need a bit of extra execution time and memory here
    core_php_time_limit::raise(HOURSECS);
    raise_memory_limit(MEMORY_EXTRA);
    tool_customlang_utils::checkout($lng, $progressbar);
    echo $output->continue_button(new moodle_url('/admin/tool/customlang/edit.php', array('lng' => $lng)), 'get');
    echo $output->footer();
    exit;
}
if ($action === 'checkin') {
    require_sesskey();
    require_capability('tool/customlang:edit', context_system::instance());
    if (empty($lng)) {
        print_error('missingparameter');
    }
Example #7
0
/**
 * Crea un archivo PDF a partir de un quiz, agregando una hoja de respuestas de opción múltiple
 * 
 * @param unknown $cm
 * @param string $debug
 * @param string $context
 * @param string $course
 * @param string $logofilepath
 * @param boolean $answersheetsonly
 * @return void|NULL
 */
function emarking_create_quiz_pdf($cm, $debug = false, $context = null, $course = null, $answersheetsonly = false, $pbar = false)
{
    global $DB, $CFG, $OUTPUT;
    // Inclusión de librerías
    require_once $CFG->dirroot . '/mod/assign/feedback/editpdf/fpdi/fpdi2tcpdf_bridge.php';
    require_once $CFG->dirroot . '/mod/assign/feedback/editpdf/fpdi/fpdi.php';
    require_once $CFG->libdir . '/pdflib.php';
    require_once $CFG->dirroot . '/mod/quiz/locallib.php';
    require_once $CFG->dirroot . '/mod/emarking/print/locallib.php';
    $filedir = $CFG->dataroot . "/temp/emarking/{$context->id}";
    emarking_initialize_directory($filedir, true);
    $fileimg = $CFG->dataroot . "/temp/emarking/{$context->id}/qr";
    emarking_initialize_directory($fileimg, true);
    $userimgdir = $CFG->dataroot . "/temp/emarking/{$context->id}/u";
    emarking_initialize_directory($userimgdir, true);
    $logofile = emarking_get_logo_file();
    $logofilepath = $logofile ? emarking_get_path_from_hash($filedir, $logofile->get_pathnamehash()) : null;
    $fullhtml = array();
    $numanswers = array();
    $attemptids = array();
    $images = array();
    $imageshtml = array();
    $users = emarking_get_enroled_students($course->id);
    if ($pbar) {
        echo $OUTPUT->heading(get_string('loadingquestions', 'mod_emarking'), 3);
        $progressbar = new progress_bar();
        $progressbar->create();
        $progressbar->update(0, count($users), get_string('processing', 'mod_emarking'));
    }
    $current = 0;
    foreach ($users as $user) {
        $current++;
        if ($pbar) {
            $progressbar->update($current, count($users), "{$user->firstname}, {$user->lastname}");
        }
        // Get the quiz object
        $quizobj = quiz::create($cm->instance, $user->id);
        // Create the new attempt and initialize the question sessions
        $attemptnumber = 1;
        $lastattempt = null;
        $timenow = time();
        // Update time now, in case the server is running really slowly.
        $attempts = quiz_get_user_attempts($quizobj->get_quizid(), $user->id, 'all');
        $numattempts = count($attempts);
        foreach ($attempts as $attempt) {
            $attemptobj = quiz_attempt::create($attempt->id);
            $slots = $attemptobj->get_slots();
            foreach ($slots as $slot) {
                $qattempt = $attemptobj->get_question_attempt($slot);
                $question = $qattempt->get_question();
                if ($question->get_type_name() === 'multianswer') {
                    $q = $question->subquestions[1];
                    $numanswers[$user->id][] = count($q->answers);
                } else {
                    if ($question->get_type_name() === 'multichoice') {
                        $numanswers[$user->id][] = count($question->answers);
                    }
                }
                $attemptids[$user->id] = $attempt->id;
                $qhtml = $attemptobj->render_question($slot, false);
                $qhtml = emarking_clean_question_html($qhtml);
                $currentimages = emarking_extract_images_url($qhtml);
                $idx = 0;
                foreach ($currentimages[1] as $imageurl) {
                    if (!array_search($imageurl, $images)) {
                        $images[] = $imageurl;
                        $imageshtml[] = $currentimages[0][$idx];
                    }
                    $idx++;
                }
                $fullhtml[$user->id][] = $qhtml;
            }
            // One attempt per user
            break;
        }
    }
    $save_to = $CFG->tempdir . '/emarking/printquiz/' . $cm->id . '/';
    emarking_initialize_directory($save_to, true);
    // Bajar las imágenes del HTML a dibujar
    $search = array();
    $replace = array();
    $replaceweb = array();
    $imagesize = array();
    $idx = 0;
    if ($pbar) {
        $progressbar->update_full(100, get_string('finished', 'mod_emarking'));
        echo $OUTPUT->heading(get_string('downloadingimages', 'mod_emarking'), 3);
        $progressbar = new progress_bar();
        $progressbar->create();
        $progressbar->update(0, count($images), get_string('processing', 'mod_emarking'));
    }
    foreach ($images as $image) {
        if ($pbar) {
            $imagefilename = explode("/", $image);
            $progressbar->update($idx + 1, count($images), $imagefilename[count($imagefilename) - 1]);
        }
        // Si solamente incluiremos hojas de respuesta terminamos el ciclo
        if ($answersheetsonly) {
            break;
        }
        if (!(list($filename, $imageinfo) = emarking_get_file_from_url($image, $save_to))) {
            echo "Problem downloading file {$image} <hr>";
        } else {
            // Buscamos el src de la imagen
            $search[] = 'src="' . $image . '"';
            $replacehtml = ' src="' . $filename . '"';
            $replacehtmlxweb = ' src="' . $image . '"';
            // Si el html de la misma contiene ancho o alto, se deja tal cual
            $imghtml = $imageshtml[$idx];
            if (substr_count($imghtml, "width") + substr_count($imghtml, "height") == 0) {
                $width = $imageinfo[0];
                $height = $imageinfo[1];
                $ratio = floatval(10) / floatval($height);
                $height = 10;
                $width = (int) ($ratio * floatval($width));
                $sizehtml = 'width="' . $width . '" height="' . $height . '"';
                $replacehtml = $sizehtml . ' ' . $replacehtml;
                $replacehtmlxweb = $sizehtml . ' ' . $replacehtmlxweb;
            }
            $replace[] = $replacehtml;
            $replaceweb[] = $replacehtmlxweb;
            $imagesize[] = $imageinfo;
        }
        $idx++;
    }
    if ($debug) {
        foreach ($fullhtml as $uid => $questions) {
            $index = 0;
            foreach ($questions as $question) {
                echo str_replace($search, $replaceweb, $fullhtml[$uid][$index]);
                $index++;
            }
        }
        return;
    }
    // Now we create the pdf file with the modified html
    $doc = new FPDI();
    $doc->setPrintHeader(false);
    $doc->setPrintFooter(false);
    $doc->SetFont('times', '', 12);
    // set margins
    $doc->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT);
    $doc->SetHeaderMargin(250);
    $doc->SetFooterMargin(PDF_MARGIN_FOOTER);
    if ($pbar) {
        $progressbar->update_full(100, get_string('finished', 'mod_emarking'));
        echo $OUTPUT->heading(get_string('creatingpdffile', 'mod_emarking'), 3);
        $progressbar = new progress_bar();
        $progressbar->create();
    }
    $current = 0;
    foreach ($fullhtml as $uid => $questions) {
        $current++;
        $stinfo = $DB->get_record('user', array('id' => $uid));
        $stinfo->name = $stinfo->firstname . ' ' . $stinfo->lastname;
        $stinfo->picture = emarking_get_student_picture($stinfo, $userimgdir);
        $stinfo->idnumber = $uid . '-' . $attemptids[$uid];
        if ($pbar) {
            $progressbar->update($current, count($fullhtml), $stinfo->name);
        }
        $groups = groups_get_user_groups($course->id, $uid);
        if ($groups && isset($groups[0][0]) && ($group = $DB->get_record('groups', array('id' => $groups[0][0])))) {
            $stinfo->group = $group->name;
        } else {
            $stinfo->group = '';
        }
        emarking_add_answer_sheet($doc, $filedir, $stinfo, $logofilepath, null, $fileimg, $course, $quizobj->get_quiz_name(), $numanswers[$uid], $attemptids[$uid]);
        // Una vez agregada la página de respuestas, si es todo lo que hay que hacer saltar al siguiente
        if ($answersheetsonly) {
            continue;
        }
        $doc->AddPage();
        emarking_draw_header($doc, $stinfo, $quizobj->get_quiz_name(), 2, $fileimg, $logofilepath, $course, null, false, 0);
        $doc->SetFont('times', '', 12);
        $doc->SetAutoPageBreak(true);
        $doc->SetXY(PDF_MARGIN_LEFT, 40);
        $index = 0;
        foreach ($questions as $question) {
            $prevy = $doc->getY();
            $fullhtml[$uid][$index] = str_replace($search, $replace, $fullhtml[$uid][$index]);
            $doc->writeHTML($fullhtml[$uid][$index]);
            $y = $doc->getY();
            $fmargin = $doc->getFooterMargin();
            $height = $doc->getPageHeight();
            $spaceleft = $height - $fmargin - $y;
            $questionsize = $y - $prevy;
            if ($spaceleft < 70) {
                $doc->AddPage();
            }
            $index++;
        }
    }
    if ($pbar) {
        $progressbar->update_full(100, get_string('finished', 'mod_emarking'));
    }
    $qid = $quizobj->get_quizid();
    $pdfquizfilename = 'quiz-' . $qid . '-' . random_string() . '.pdf';
    $fs = get_file_storage();
    $filerecord = array('component' => 'mod_emarking', 'filearea' => 'pdfquiz', 'contextid' => $context->id, 'itemid' => $quizobj->get_quizid(), 'filepath' => '/', 'filename' => $pdfquizfilename);
    $doc->Output($filedir . '/' . $pdfquizfilename, 'F');
    $file = $fs->create_file_from_pathname($filerecord, $filedir . '/' . $pdfquizfilename);
    $downloadurl = moodle_url::make_file_url("{$CFG->wwwroot}/pluginfile.php", "/{$context->id}/mod_emarking/pdfquiz/{$qid}/{$pdfquizfilename}", null, true);
    return $downloadurl;
}
Example #8
0
                continue;
            }
            emarking_insert_user_answers($choices, $user, $attemptid);
        }
        echo $OUTPUT->notification(get_string('csvimportsuccessfull', 'mod_emarking'), 'notifysuccess');
        echo $OUTPUT->single_button(new moodle_url('/mod/emarking/orm/processomr.php', array('cmid' => $cm->id, 'finish' => true)), get_string('finish', 'mod_emarking'));
    } else {
        $answersform->display();
    }
    echo $OUTPUT->footer();
    die;
}
// Get the users enrolled
$users = emarking_get_enroled_students($course->id);
$pbar = new progress_bar();
$pbar->create();
if ($create) {
    quiz_delete_all_attempts($quiz);
}
$cur = 1;
$total = count($users);
// Insert answers or finish the attempt for each student
foreach ($users as $user) {
    $pbar->update($cur, $total, get_string('processing', 'mod_emarking') . $user->lastname . $user->firstname);
    flush();
    // Get the quiz instance for the specific student
    $quizobj = quiz::create($cm->instance, $user->id);
    // Get all the attempts
    $attempts = quiz_get_user_attempts($quizobj->get_quizid(), $user->id, 'all');
    if ($create) {
        emarking_add_user_attempt($cm, $user);
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.
}