Beispiel #1
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();

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

    if ($oldversion < 2011120700) {

        // Define field lastcron to be dropped from quiz_reports.
        $table = new xmldb_table('quiz_reports');
        $field = new xmldb_field('lastcron');

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

        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2011120700, 'quiz');
    }

    if ($oldversion < 2011120701) {

        // Define field cron to be dropped from quiz_reports.
        $table = new xmldb_table('quiz_reports');
        $field = new xmldb_field('cron');

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

        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2011120701, 'quiz');
    }

    if ($oldversion < 2011120703) {
        // Track page of quiz attempts.
        $table = new xmldb_table('quiz_attempts');

        $field = new xmldb_field('currentpage', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 0);

        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }
        upgrade_mod_savepoint(true, 2011120703, 'quiz');
    }

    if ($oldversion < 2012030901) {
        // Configuration option for navigation method.
        $table = new xmldb_table('quiz');

        $field = new xmldb_field('navmethod', XMLDB_TYPE_CHAR, '16', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 'free');

        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }
        upgrade_mod_savepoint(true, 2012030901, 'quiz');
    }

    if ($oldversion < 2012040198) {
        // This step was added later. In MDL-32727, it was found that adding the
        // unique index on quiz-userid-attempt sometimes failed because of
        // duplicate entries {quizid}-{userid}-{attempt}. We do two things to
        // prevent these problems. First, here, we delete all preview attempts.

        // This code is an approximate copy-and-paste from
        // question_engine_data_mapper::delete_questions_usage_by_activities
        // Note that, for simplicity, the MySQL performance hack has been removed.
        // Since this code is for upgrade only, performance in not so critical,
        // where as simplicity of testing the code is.

        // Note that there is a limit to how far I am prepared to go in eliminating
        // all calls to library functions in this upgrade code. The only library
        // function still being used in question_engine::get_all_response_file_areas();
        // I think it is pretty safe not to inline it here.

        // Get a list of response variables that have files.
        require_once($CFG->dirroot . '/question/type/questiontypebase.php');
        $variables = array();
        foreach (core_component::get_plugin_list('qtype') as $qtypename => $path) {
            $file = $path . '/questiontype.php';
            if (!is_readable($file)) {
                continue;
            }
            include_once($file);
            $class = 'qtype_' . $qtypename;
            if (!class_exists($class)) {
                continue;
            }
            $qtype = new $class();
            if (!method_exists($qtype, 'response_file_areas')) {
                continue;
            }
            $variables += $qtype->response_file_areas();
        }

        // Conver that to a list of actual file area names.
        $fileareas = array();
        foreach (array_unique($variables) as $variable) {
            $fileareas[] = 'response_' . $variable;
        }
        // No point checking if this is empty as an optimisation, because essay
        // has response file areas, so the array will never be empty.

        // Get all the contexts where there are previews.
        $contextids = $DB->get_records_sql_menu("
                SELECT DISTINCT qu.contextid, 1
                  FROM {question_usages} qu
                  JOIN {quiz_attempts} quiza ON quiza.uniqueid = qu.id
                 WHERE quiza.preview = 1");

        // Loop over contexts and files areas, deleting all files.
        $fs = get_file_storage();
        foreach ($contextids as $contextid => $notused) {
            foreach ($fileareas as $filearea) {
                upgrade_set_timeout(300);
                $fs->delete_area_files_select($contextid, 'question', $filearea,
                        "IN (SELECT qas.id
                               FROM {question_attempt_steps} qas
                               JOIN {question_attempts} qa ON qa.id = qas.questionattemptid
                               JOIN {quiz_attempts} quiza ON quiza.uniqueid = qa.questionusageid
                              WHERE quiza.preview = 1)");
            }
        }

        // Now delete the question data associated with the previews.
        $DB->delete_records_select('question_attempt_step_data', "attemptstepid IN (
                SELECT qas.id
                  FROM {question_attempt_steps} qas
                  JOIN {question_attempts} qa ON qa.id = qas.questionattemptid
                  JOIN {quiz_attempts} quiza ON quiza.uniqueid = qa.questionusageid
                 WHERE quiza.preview = 1)");

        $DB->delete_records_select('question_attempt_steps', "questionattemptid IN (
                SELECT qa.id
                  FROM {question_attempts} qa
                  JOIN {quiz_attempts} quiza ON quiza.uniqueid = qa.questionusageid
                 WHERE quiza.preview = 1)");

        $DB->delete_records_select('question_attempts', "{question_attempts}.questionusageid IN (
                SELECT uniqueid FROM {quiz_attempts} WHERE preview = 1)");

        $DB->delete_records_select('question_usages', "{question_usages}.id IN (
                SELECT uniqueid FROM {quiz_attempts} WHERE preview = 1)");

        // Finally delete the previews.
        $DB->delete_records('quiz_attempts', array('preview' => 1));

        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2012040198, 'quiz');
    }

    if ($oldversion < 2012040199) {
        // This step was added later. In MDL-32727, it was found that adding the
        // unique index on quiz-userid-attempt sometimes failed because of
        // duplicate entries {quizid}-{userid}-{attempt}.
        // Here, if there are still duplicate entires, we renumber the values in
        // the attempt column.

        // Load all the problem quiz attempts.
        $problems = $DB->get_recordset_sql('
                SELECT qa.id, qa.quiz, qa.userid, qa.attempt
                  FROM {quiz_attempts} qa
                  JOIN (
                          SELECT DISTINCT quiz, userid
                            FROM {quiz_attempts}
                        GROUP BY quiz, userid, attempt
                          HAVING COUNT(1) > 1
                       ) problems_view ON problems_view.quiz = qa.quiz AND
                                          problems_view.userid = qa.userid
              ORDER BY qa.quiz, qa.userid, qa.attempt, qa.id');

        // Renumber them.
        $currentquiz = null;
        $currentuserid = null;
        $attempt = 1;
        foreach ($problems as $problem) {
            if ($problem->quiz !== $currentquiz || $problem->userid !== $currentuserid) {
                $currentquiz = $problem->quiz;
                $currentuserid = $problem->userid;
                $attempt = 1;
            }
            if ($attempt != $problem->attempt) {
                $DB->set_field('quiz_attempts', 'attempt', $attempt, array('id' => $problem->id));
            }
            $attempt += 1;
        }

        $problems->close();

        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2012040199, 'quiz');
    }

    if ($oldversion < 2012040200) {
        // Define index userid to be dropped form quiz_attempts
        $table = new xmldb_table('quiz_attempts');
        $index = new xmldb_index('userid', XMLDB_INDEX_NOTUNIQUE, array('userid'));

        // Conditionally launch drop index quiz-userid-attempt.
        if ($dbman->index_exists($table, $index)) {
            $dbman->drop_index($table, $index);
        }

        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2012040200, 'quiz');
    }

    if ($oldversion < 2012040201) {

        // Define key userid (foreign) to be added to quiz_attempts.
        $table = new xmldb_table('quiz_attempts');
        $key = new xmldb_key('userid', XMLDB_KEY_FOREIGN, array('userid'), 'user', array('id'));

        // Launch add key userid.
        $dbman->add_key($table, $key);

        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2012040201, 'quiz');
    }

    if ($oldversion < 2012040202) {

        // Define index quiz-userid-attempt (unique) to be added to quiz_attempts.
        $table = new xmldb_table('quiz_attempts');
        $index = new xmldb_index('quiz-userid-attempt', XMLDB_INDEX_UNIQUE, array('quiz', 'userid', 'attempt'));

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

        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2012040202, 'quiz');
    }

    if ($oldversion < 2012040203) {

        // Define field state to be added to quiz_attempts.
        $table = new xmldb_table('quiz_attempts');
        $field = new xmldb_field('state', XMLDB_TYPE_CHAR, '16', null, XMLDB_NOTNULL, null, 'inprogress', 'preview');

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

        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2012040203, 'quiz');
    }

    if ($oldversion < 2012040204) {

        // Update quiz_attempts.state for finished attempts.
        $DB->set_field_select('quiz_attempts', 'state', 'finished', 'timefinish > 0');

        // Other, more complex transitions (basically abandoned attempts), will
        // be handled by cron later.

        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2012040204, 'quiz');
    }

    if ($oldversion < 2012040205) {

        // Define field overduehandling to be added to quiz.
        $table = new xmldb_table('quiz');
        $field = new xmldb_field('overduehandling', XMLDB_TYPE_CHAR, '16', null, XMLDB_NOTNULL, null, 'autoabandon', 'timelimit');

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

        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2012040205, 'quiz');
    }

    if ($oldversion < 2012040206) {

        // Define field graceperiod to be added to quiz.
        $table = new xmldb_table('quiz');
        $field = new xmldb_field('graceperiod', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'overduehandling');

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

        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2012040206, 'quiz');
    }

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

    if ($oldversion < 2012061702) {

        // MDL-32791 somebody reported having nonsense rows in their
        // quiz_question_instances which caused various problems. These rows
        // are meaningless, hence this upgrade step to clean them up.
        $DB->delete_records('quiz_question_instances', array('question' => 0));

        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2012061702, 'quiz');
    }

    if ($oldversion < 2012061703) {

        // MDL-34702 the questiondecimalpoints column was created with default -2
        // when it should have been -1, and no-one has noticed in the last 2+ years!

        // Changing the default of field questiondecimalpoints on table quiz to -1.
        $table = new xmldb_table('quiz');
        $field = new xmldb_field('questiondecimalpoints', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, '-1', 'decimalpoints');

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

        // Correct any wrong values.
        $DB->set_field('quiz', 'questiondecimalpoints', -1, array('questiondecimalpoints' => -2));

        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2012061703, 'quiz');
    }

    if ($oldversion < 2012100801) {

        // Define field timecheckstate to be added to quiz_attempts
        $table = new xmldb_table('quiz_attempts');
        $field = new xmldb_field('timecheckstate', XMLDB_TYPE_INTEGER, '10', null, null, null, '0', 'timemodified');

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

        // Define index state-timecheckstate (not unique) to be added to quiz_attempts
        $table = new xmldb_table('quiz_attempts');
        $index = new xmldb_index('state-timecheckstate', XMLDB_INDEX_NOTUNIQUE, array('state', 'timecheckstate'));

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

        // Overdue cron no longer needs these
        unset_config('overduelastrun', 'quiz');
        unset_config('overduedoneto', 'quiz');

        // Update timecheckstate on all open attempts
        require_once($CFG->dirroot . '/mod/quiz/locallib.php');
        quiz_update_open_attempts(array());

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

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

    if ($oldversion < 2013031900) {
        // Quiz manual grading UI should be controlled by mod/quiz:grade, not :viewreports.
        $DB->set_field('quiz_reports', 'capability', 'mod/quiz:grade', array('name' => 'grading'));

        // Mod quiz savepoint reached.
        upgrade_mod_savepoint(true, 2013031900, 'quiz');
    }

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


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

    if ($oldversion < 2014011300) {

        // Define key quiz (foreign) to be dropped form quiz_question_instances.
        $table = new xmldb_table('quiz_question_instances');
        $key = new xmldb_key('quiz', XMLDB_KEY_FOREIGN, array('quiz'), 'quiz', array('id'));

        // Launch drop key quiz.
        $dbman->drop_key($table, $key);

        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2014011300, 'quiz');
    }

    if ($oldversion < 2014011301) {

        // Rename field quiz on table quiz_question_instances to quizid.
        $table = new xmldb_table('quiz_question_instances');
        $field = new xmldb_field('quiz', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'id');

        // Launch rename field quiz.
        $dbman->rename_field($table, $field, 'quizid');

        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2014011301, 'quiz');
    }

    if ($oldversion < 2014011302) {

        // Define key quizid (foreign) to be added to quiz_question_instances.
        $table = new xmldb_table('quiz_question_instances');
        $key = new xmldb_key('quizid', XMLDB_KEY_FOREIGN, array('quizid'), 'quiz', array('id'));

        // Launch add key quizid.
        $dbman->add_key($table, $key);

        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2014011302, 'quiz');
    }

    if ($oldversion < 2014011303) {

        // Define key question (foreign) to be dropped form quiz_question_instances.
        $table = new xmldb_table('quiz_question_instances');
        $key = new xmldb_key('question', XMLDB_KEY_FOREIGN, array('question'), 'question', array('id'));

        // Launch drop key question.
        $dbman->drop_key($table, $key);

        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2014011303, 'quiz');
    }

    if ($oldversion < 2014011304) {

        // Rename field question on table quiz_question_instances to questionid.
        $table = new xmldb_table('quiz_question_instances');
        $field = new xmldb_field('question', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'quiz');

        // Launch rename field question.
        $dbman->rename_field($table, $field, 'questionid');

        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2014011304, 'quiz');
    }

    if ($oldversion < 2014011305) {

        // Define key questionid (foreign) to be added to quiz_question_instances.
        $table = new xmldb_table('quiz_question_instances');
        $key = new xmldb_key('questionid', XMLDB_KEY_FOREIGN, array('questionid'), 'question', array('id'));

        // Launch add key questionid.
        $dbman->add_key($table, $key);

        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2014011305, 'quiz');
    }

    if ($oldversion < 2014011306) {

        // Rename field grade on table quiz_question_instances to maxmark.
        $table = new xmldb_table('quiz_question_instances');
        $field = new xmldb_field('grade', XMLDB_TYPE_NUMBER, '12, 7', null, XMLDB_NOTNULL, null, '0', 'question');

        // Launch rename field grade.
        $dbman->rename_field($table, $field, 'maxmark');

        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2014011306, 'quiz');
    }

    return true;
}
Beispiel #2
0
            } else {
                unset($fromform->id);
                $fromform->id = $DB->insert_record('quiz_overrides', $fromform);
                // Determine which override created event to fire.
                $params['objectid'] = $fromform->id;
                if (!$groupmode) {
                    $params['relateduserid'] = $fromform->userid;
                    $event = \mod_quiz\event\user_override_created::create($params);
                } else {
                    $params['other']['groupid'] = $fromform->groupid;
                    $event = \mod_quiz\event\group_override_created::create($params);
                }
                // Trigger the override created event.
                $event->trigger();
            }
            quiz_update_open_attempts(array('quizid' => $quiz->id));
            quiz_update_events($quiz, $fromform);
            if (!empty($fromform->submitbutton)) {
                redirect($overridelisturl);
            }
            // The user pressed the 'again' button, so redirect back to this page.
            $url->remove_params('cmid');
            $url->param('action', 'duplicate');
            $url->param('id', $fromform->id);
            redirect($url);
        }
    }
}
// Print the form.
$pagetitle = get_string('editoverride', 'quiz');
$PAGE->navbar->add($pagetitle);
Beispiel #3
0
/**
 * Handle groups_members_removed event
 *
 * @param object $event the event object.
 */
function quiz_groups_members_removed_handler($event) {
    if ($event->userid == 0) {
        quiz_update_open_attempts(array('courseid'=>$event->courseid));
    } else {
        quiz_update_open_attempts(array('courseid'=>$event->courseid, 'userid'=>$event->userid));
    }
}
Beispiel #4
0
/**
 * Handle groups_members_removed event
 *
 * @param object $event the event object.
 * @deprecated since 2.6, see {@link \mod_quiz\group_observers::group_member_removed()}.
 */
function quiz_groups_members_removed_handler($event) {
    debugging('quiz_groups_members_removed_handler() is deprecated, please use ' .
        '\mod_quiz\group_observers::group_member_removed() instead.', DEBUG_DEVELOPER);
    if ($event->userid == 0) {
        quiz_update_open_attempts(array('courseid'=>$event->courseid));
    } else {
        quiz_update_open_attempts(array('courseid'=>$event->courseid, 'userid'=>$event->userid));
    }
}
Beispiel #5
0
/**
 * Given an object containing all the necessary data,
 * (defined by the form in mod_form.php) this function
 * will update an existing instance with new data.
 *
 * @param object $quiz the data that came from the form.
 * @return mixed true on success, false or a string error message on failure.
 */
function quiz_update_instance($quiz, $mform)
{
    global $CFG, $DB;
    require_once $CFG->dirroot . '/mod/quiz/locallib.php';
    // Process the options from the form.
    $result = quiz_process_options($quiz);
    if ($result && is_string($result)) {
        return $result;
    }
    // Get the current value, so we can see what changed.
    $oldquiz = $DB->get_record('quiz', array('id' => $quiz->instance));
    // We need two values from the existing DB record that are not in the form,
    // in some of the function calls below.
    $quiz->sumgrades = $oldquiz->sumgrades;
    $quiz->grade = $oldquiz->grade;
    // Repaginate, if asked to.
    if (!$quiz->shufflequestions && !empty($quiz->repaginatenow)) {
        $quiz->questions = quiz_repaginate(quiz_clean_layout($oldquiz->questions, true), $quiz->questionsperpage);
    }
    unset($quiz->repaginatenow);
    // Update the database.
    $quiz->id = $quiz->instance;
    $DB->update_record('quiz', $quiz);
    // Do the processing required after an add or an update.
    quiz_after_add_or_update($quiz);
    if ($oldquiz->grademethod != $quiz->grademethod) {
        quiz_update_all_final_grades($quiz);
        quiz_update_grades($quiz);
    }
    $quizdateschanged = $oldquiz->timelimit != $quiz->timelimit || $oldquiz->timeclose != $quiz->timeclose || $oldquiz->graceperiod != $quiz->graceperiod;
    if ($quizdateschanged) {
        quiz_update_open_attempts(array('quizid' => $quiz->id));
    }
    // Delete any previous preview attempts.
    quiz_delete_previews($quiz);
    return true;
}
/**
 * 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();
    // Moodle v2.2.0 release upgrade line.
    // Put any upgrade step following this.
    if ($oldversion < 2011120700) {
        // Define field lastcron to be dropped from quiz_reports.
        $table = new xmldb_table('quiz_reports');
        $field = new xmldb_field('lastcron');
        // Conditionally launch drop field lastcron.
        if ($dbman->field_exists($table, $field)) {
            $dbman->drop_field($table, $field);
        }
        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2011120700, 'quiz');
    }
    if ($oldversion < 2011120701) {
        // Define field cron to be dropped from quiz_reports.
        $table = new xmldb_table('quiz_reports');
        $field = new xmldb_field('cron');
        // Conditionally launch drop field cron.
        if ($dbman->field_exists($table, $field)) {
            $dbman->drop_field($table, $field);
        }
        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2011120701, 'quiz');
    }
    if ($oldversion < 2011120703) {
        // Track page of quiz attempts.
        $table = new xmldb_table('quiz_attempts');
        $field = new xmldb_field('currentpage', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 0);
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }
        upgrade_mod_savepoint(true, 2011120703, 'quiz');
    }
    if ($oldversion < 2012030901) {
        // Configuration option for navigation method.
        $table = new xmldb_table('quiz');
        $field = new xmldb_field('navmethod', XMLDB_TYPE_CHAR, '16', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 'free');
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }
        upgrade_mod_savepoint(true, 2012030901, 'quiz');
    }
    if ($oldversion < 2012040198) {
        // This step was added later. In MDL-32727, it was found that adding the
        // unique index on quiz-userid-attempt sometimes failed because of
        // duplicate entries {quizid}-{userid}-{attempt}. We do two things to
        // prevent these problems. First, here, we delete all preview attempts.
        // This code is an approximate copy-and-paste from
        // question_engine_data_mapper::delete_questions_usage_by_activities
        // Note that, for simplicity, the MySQL performance hack has been removed.
        // Since this code is for upgrade only, performance in not so critical,
        // where as simplicity of testing the code is.
        // Note that there is a limit to how far I am prepared to go in eliminating
        // all calls to library functions in this upgrade code. The only library
        // function still being used in question_engine::get_all_response_file_areas();
        // I think it is pretty safe not to inline it here.
        // Get a list of response variables that have files.
        require_once $CFG->dirroot . '/question/type/questiontypebase.php';
        $variables = array();
        foreach (core_component::get_plugin_list('qtype') as $qtypename => $path) {
            $file = $path . '/questiontype.php';
            if (!is_readable($file)) {
                continue;
            }
            include_once $file;
            $class = 'qtype_' . $qtypename;
            if (!class_exists($class)) {
                continue;
            }
            $qtype = new $class();
            if (!method_exists($qtype, 'response_file_areas')) {
                continue;
            }
            $variables += $qtype->response_file_areas();
        }
        // Conver that to a list of actual file area names.
        $fileareas = array();
        foreach (array_unique($variables) as $variable) {
            $fileareas[] = 'response_' . $variable;
        }
        // No point checking if this is empty as an optimisation, because essay
        // has response file areas, so the array will never be empty.
        // Get all the contexts where there are previews.
        $contextids = $DB->get_records_sql_menu("\n                SELECT DISTINCT qu.contextid, 1\n                  FROM {question_usages} qu\n                  JOIN {quiz_attempts} quiza ON quiza.uniqueid = qu.id\n                 WHERE quiza.preview = 1");
        // Loop over contexts and files areas, deleting all files.
        $fs = get_file_storage();
        foreach ($contextids as $contextid => $notused) {
            foreach ($fileareas as $filearea) {
                upgrade_set_timeout(300);
                $fs->delete_area_files_select($contextid, 'question', $filearea, "IN (SELECT qas.id\n                               FROM {question_attempt_steps} qas\n                               JOIN {question_attempts} qa ON qa.id = qas.questionattemptid\n                               JOIN {quiz_attempts} quiza ON quiza.uniqueid = qa.questionusageid\n                              WHERE quiza.preview = 1)");
            }
        }
        // Now delete the question data associated with the previews.
        $DB->delete_records_select('question_attempt_step_data', "attemptstepid IN (\n                SELECT qas.id\n                  FROM {question_attempt_steps} qas\n                  JOIN {question_attempts} qa ON qa.id = qas.questionattemptid\n                  JOIN {quiz_attempts} quiza ON quiza.uniqueid = qa.questionusageid\n                 WHERE quiza.preview = 1)");
        $DB->delete_records_select('question_attempt_steps', "questionattemptid IN (\n                SELECT qa.id\n                  FROM {question_attempts} qa\n                  JOIN {quiz_attempts} quiza ON quiza.uniqueid = qa.questionusageid\n                 WHERE quiza.preview = 1)");
        $DB->delete_records_select('question_attempts', "{question_attempts}.questionusageid IN (\n                SELECT uniqueid FROM {quiz_attempts} WHERE preview = 1)");
        $DB->delete_records_select('question_usages', "{question_usages}.id IN (\n                SELECT uniqueid FROM {quiz_attempts} WHERE preview = 1)");
        // Finally delete the previews.
        $DB->delete_records('quiz_attempts', array('preview' => 1));
        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2012040198, 'quiz');
    }
    if ($oldversion < 2012040199) {
        // This step was added later. In MDL-32727, it was found that adding the
        // unique index on quiz-userid-attempt sometimes failed because of
        // duplicate entries {quizid}-{userid}-{attempt}.
        // Here, if there are still duplicate entires, we renumber the values in
        // the attempt column.
        // Load all the problem quiz attempts.
        $problems = $DB->get_recordset_sql('
                SELECT qa.id, qa.quiz, qa.userid, qa.attempt
                  FROM {quiz_attempts} qa
                  JOIN (
                          SELECT DISTINCT quiz, userid
                            FROM {quiz_attempts}
                        GROUP BY quiz, userid, attempt
                          HAVING COUNT(1) > 1
                       ) problems_view ON problems_view.quiz = qa.quiz AND
                                          problems_view.userid = qa.userid
              ORDER BY qa.quiz, qa.userid, qa.attempt, qa.id');
        // Renumber them.
        $currentquiz = null;
        $currentuserid = null;
        $attempt = 1;
        foreach ($problems as $problem) {
            if ($problem->quiz !== $currentquiz || $problem->userid !== $currentuserid) {
                $currentquiz = $problem->quiz;
                $currentuserid = $problem->userid;
                $attempt = 1;
            }
            if ($attempt != $problem->attempt) {
                $DB->set_field('quiz_attempts', 'attempt', $attempt, array('id' => $problem->id));
            }
            $attempt += 1;
        }
        $problems->close();
        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2012040199, 'quiz');
    }
    if ($oldversion < 2012040200) {
        // Define index userid to be dropped form quiz_attempts
        $table = new xmldb_table('quiz_attempts');
        $index = new xmldb_index('userid', XMLDB_INDEX_NOTUNIQUE, array('userid'));
        // Conditionally launch drop index quiz-userid-attempt.
        if ($dbman->index_exists($table, $index)) {
            $dbman->drop_index($table, $index);
        }
        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2012040200, 'quiz');
    }
    if ($oldversion < 2012040201) {
        // Define key userid (foreign) to be added to quiz_attempts.
        $table = new xmldb_table('quiz_attempts');
        $key = new xmldb_key('userid', XMLDB_KEY_FOREIGN, array('userid'), 'user', array('id'));
        // Launch add key userid.
        $dbman->add_key($table, $key);
        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2012040201, 'quiz');
    }
    if ($oldversion < 2012040202) {
        // Define index quiz-userid-attempt (unique) to be added to quiz_attempts.
        $table = new xmldb_table('quiz_attempts');
        $index = new xmldb_index('quiz-userid-attempt', XMLDB_INDEX_UNIQUE, array('quiz', 'userid', 'attempt'));
        // Conditionally launch add index quiz-userid-attempt.
        if (!$dbman->index_exists($table, $index)) {
            $dbman->add_index($table, $index);
        }
        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2012040202, 'quiz');
    }
    if ($oldversion < 2012040203) {
        // Define field state to be added to quiz_attempts.
        $table = new xmldb_table('quiz_attempts');
        $field = new xmldb_field('state', XMLDB_TYPE_CHAR, '16', null, XMLDB_NOTNULL, null, 'inprogress', 'preview');
        // Conditionally launch add field state.
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }
        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2012040203, 'quiz');
    }
    if ($oldversion < 2012040204) {
        // Update quiz_attempts.state for finished attempts.
        $DB->set_field_select('quiz_attempts', 'state', 'finished', 'timefinish > 0');
        // Other, more complex transitions (basically abandoned attempts), will
        // be handled by cron later.
        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2012040204, 'quiz');
    }
    if ($oldversion < 2012040205) {
        // Define field overduehandling to be added to quiz.
        $table = new xmldb_table('quiz');
        $field = new xmldb_field('overduehandling', XMLDB_TYPE_CHAR, '16', null, XMLDB_NOTNULL, null, 'autoabandon', 'timelimit');
        // Conditionally launch add field overduehandling.
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }
        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2012040205, 'quiz');
    }
    if ($oldversion < 2012040206) {
        // Define field graceperiod to be added to quiz.
        $table = new xmldb_table('quiz');
        $field = new xmldb_field('graceperiod', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'overduehandling');
        // Conditionally launch add field graceperiod.
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }
        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2012040206, 'quiz');
    }
    // Moodle v2.3.0 release upgrade line
    // Put any upgrade step following this
    if ($oldversion < 2012061702) {
        // MDL-32791 somebody reported having nonsense rows in their
        // quiz_question_instances which caused various problems. These rows
        // are meaningless, hence this upgrade step to clean them up.
        $DB->delete_records('quiz_question_instances', array('question' => 0));
        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2012061702, 'quiz');
    }
    if ($oldversion < 2012061703) {
        // MDL-34702 the questiondecimalpoints column was created with default -2
        // when it should have been -1, and no-one has noticed in the last 2+ years!
        // Changing the default of field questiondecimalpoints on table quiz to -1.
        $table = new xmldb_table('quiz');
        $field = new xmldb_field('questiondecimalpoints', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, '-1', 'decimalpoints');
        // Launch change of default for field questiondecimalpoints.
        $dbman->change_field_default($table, $field);
        // Correct any wrong values.
        $DB->set_field('quiz', 'questiondecimalpoints', -1, array('questiondecimalpoints' => -2));
        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2012061703, 'quiz');
    }
    if ($oldversion < 2012100801) {
        // Define field timecheckstate to be added to quiz_attempts
        $table = new xmldb_table('quiz_attempts');
        $field = new xmldb_field('timecheckstate', XMLDB_TYPE_INTEGER, '10', null, null, null, '0', 'timemodified');
        // Conditionally launch add field timecheckstate
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }
        // Define index state-timecheckstate (not unique) to be added to quiz_attempts
        $table = new xmldb_table('quiz_attempts');
        $index = new xmldb_index('state-timecheckstate', XMLDB_INDEX_NOTUNIQUE, array('state', 'timecheckstate'));
        // Conditionally launch add index state-timecheckstate
        if (!$dbman->index_exists($table, $index)) {
            $dbman->add_index($table, $index);
        }
        // Overdue cron no longer needs these
        unset_config('overduelastrun', 'quiz');
        unset_config('overduedoneto', 'quiz');
        // Update timecheckstate on all open attempts
        require_once $CFG->dirroot . '/mod/quiz/locallib.php';
        quiz_update_open_attempts(array());
        // quiz savepoint reached
        upgrade_mod_savepoint(true, 2012100801, 'quiz');
    }
    // Moodle v2.4.0 release upgrade line
    // Put any upgrade step following this
    if ($oldversion < 2013031900) {
        // Quiz manual grading UI should be controlled by mod/quiz:grade, not :viewreports.
        $DB->set_field('quiz_reports', 'capability', 'mod/quiz:grade', array('name' => 'grading'));
        // Mod quiz savepoint reached.
        upgrade_mod_savepoint(true, 2013031900, 'quiz');
    }
    // Moodle v2.5.0 release upgrade line.
    // Put any upgrade step following this.
    // Moodle v2.6.0 release upgrade line.
    // Put any upgrade step following this.
    if ($oldversion < 2014011300) {
        // Define key quiz (foreign) to be dropped form quiz_question_instances.
        $table = new xmldb_table('quiz_question_instances');
        $key = new xmldb_key('quiz', XMLDB_KEY_FOREIGN, array('quiz'), 'quiz', array('id'));
        // Launch drop key quiz.
        $dbman->drop_key($table, $key);
        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2014011300, 'quiz');
    }
    if ($oldversion < 2014011301) {
        // Rename field quiz on table quiz_question_instances to quizid.
        $table = new xmldb_table('quiz_question_instances');
        $field = new xmldb_field('quiz', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'id');
        // Launch rename field quiz.
        $dbman->rename_field($table, $field, 'quizid');
        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2014011301, 'quiz');
    }
    if ($oldversion < 2014011302) {
        // Define key quizid (foreign) to be added to quiz_question_instances.
        $table = new xmldb_table('quiz_question_instances');
        $key = new xmldb_key('quizid', XMLDB_KEY_FOREIGN, array('quizid'), 'quiz', array('id'));
        // Launch add key quizid.
        $dbman->add_key($table, $key);
        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2014011302, 'quiz');
    }
    if ($oldversion < 2014011303) {
        // Define key question (foreign) to be dropped form quiz_question_instances.
        $table = new xmldb_table('quiz_question_instances');
        $key = new xmldb_key('question', XMLDB_KEY_FOREIGN, array('question'), 'question', array('id'));
        // Launch drop key question.
        $dbman->drop_key($table, $key);
        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2014011303, 'quiz');
    }
    if ($oldversion < 2014011304) {
        // Rename field question on table quiz_question_instances to questionid.
        $table = new xmldb_table('quiz_question_instances');
        $field = new xmldb_field('question', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'quiz');
        // Launch rename field question.
        $dbman->rename_field($table, $field, 'questionid');
        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2014011304, 'quiz');
    }
    if ($oldversion < 2014011305) {
        // Define key questionid (foreign) to be added to quiz_question_instances.
        $table = new xmldb_table('quiz_question_instances');
        $key = new xmldb_key('questionid', XMLDB_KEY_FOREIGN, array('questionid'), 'question', array('id'));
        // Launch add key questionid.
        $dbman->add_key($table, $key);
        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2014011305, 'quiz');
    }
    if ($oldversion < 2014011306) {
        // Rename field grade on table quiz_question_instances to maxmark.
        $table = new xmldb_table('quiz_question_instances');
        $field = new xmldb_field('grade', XMLDB_TYPE_NUMBER, '12, 7', null, XMLDB_NOTNULL, null, '0', 'question');
        // Launch rename field grade.
        $dbman->rename_field($table, $field, 'maxmark');
        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2014011306, 'quiz');
    }
    if ($oldversion < 2014021300) {
        // Define field needsupgradetonewqe to be dropped from quiz_attempts.
        $table = new xmldb_table('quiz_attempts');
        $field = new xmldb_field('needsupgradetonewqe');
        // Conditionally launch drop field needsupgradetonewqe.
        if ($dbman->field_exists($table, $field)) {
            $dbman->drop_field($table, $field);
        }
        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2014021300, 'quiz');
    }
    if ($oldversion < 2014022000) {
        // Define table quiz_question_instances to be renamed to quiz_slots.
        $table = new xmldb_table('quiz_question_instances');
        // Launch rename table for quiz_question_instances.
        $dbman->rename_table($table, 'quiz_slots');
        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2014022000, 'quiz');
    }
    if ($oldversion < 2014022001) {
        // Define field slot to be added to quiz_slots.
        $table = new xmldb_table('quiz_slots');
        $field = new xmldb_field('slot', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'id');
        // Conditionally launch add field slot.
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }
        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2014022001, 'quiz');
    }
    if ($oldversion < 2014022002) {
        // Define field page to be added to quiz_slots.
        $table = new xmldb_table('quiz_slots');
        $field = new xmldb_field('page', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'quizid');
        // Conditionally launch add field page.
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }
        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2014022002, 'quiz');
    }
    if ($oldversion < 2014022003) {
        // Use the information in the old quiz.questions column to fill in the
        // new slot and page columns.
        $numquizzes = $DB->count_records('quiz');
        if ($numquizzes > 0) {
            $pbar = new progress_bar('quizquestionstoslots', 500, true);
            $transaction = $DB->start_delegated_transaction();
            $numberdone = 0;
            $quizzes = $DB->get_recordset('quiz', null, 'id', 'id,questions,sumgrades');
            foreach ($quizzes as $quiz) {
                if ($quiz->questions === '') {
                    $questionsinorder = array();
                } else {
                    $questionsinorder = explode(',', $quiz->questions);
                }
                $questionidtoslotrowid = $DB->get_records_menu('quiz_slots', array('quizid' => $quiz->id), '', 'id, questionid');
                $problemfound = false;
                $currentpage = 1;
                $slot = 1;
                foreach ($questionsinorder as $questionid) {
                    if ($questionid === '0') {
                        // Page break.
                        $currentpage++;
                        continue;
                    }
                    if ($questionid === '') {
                        // This can happen as the result of old restore bugs.
                        // There can be a missing number in the list of ids.
                        // All we can do about this is ignore it, which is what
                        // the quiz system used to do. See MDL-45321.
                        continue;
                    }
                    $key = array_search($questionid, $questionidtoslotrowid);
                    if ($key !== false) {
                        // Normal case. quiz_slots entry is present.
                        // Just need to add slot and page.
                        $quizslot = new stdClass();
                        $quizslot->id = $key;
                        $quizslot->slot = $slot;
                        $quizslot->page = $currentpage;
                        $DB->update_record('quiz_slots', $quizslot);
                        unset($questionidtoslotrowid[$key]);
                        // So we can do a sanity check later.
                        $slot++;
                        continue;
                    } else {
                        // This should not happen. The question was listed in
                        // quiz.questions, but there was not an entry for it in
                        // quiz_slots (formerly quiz_question_instances).
                        // Previously, if such question ids were found, then
                        // starting an attempt at the quiz would throw an exception.
                        // Here, we try to add the missing data.
                        $problemfound = true;
                        $defaultmark = $DB->get_field('question', 'defaultmark', array('id' => $questionid), IGNORE_MISSING);
                        if ($defaultmark === false) {
                            debugging('During upgrade, detected that question ' . $questionid . ' was listed as being part of quiz ' . $quiz->id . ' but this question no longer exists. Ignoring it.', DEBUG_NORMAL);
                            // Non-existent question. Ignore it completely.
                            continue;
                        }
                        debugging('During upgrade, detected that question ' . $questionid . ' was listed as being part of quiz ' . $quiz->id . ' but there was not entry for it in ' . 'quiz_question_instances/quiz_slots. Creating an entry with default mark.', DEBUG_NORMAL);
                        $quizslot = new stdClass();
                        $quizslot->quizid = $quiz->id;
                        $quizslot->slot = $slot;
                        $quizslot->page = $currentpage;
                        $quizslot->questionid = $questionid;
                        $quizslot->maxmark = $defaultmark;
                        $DB->insert_record('quiz_slots', $quizslot);
                        $slot++;
                        continue;
                    }
                }
                // Now, as a sanity check, ensure we have done all the
                // quiz_slots rows linked to this quiz.
                if (!empty($questionidtoslotrowid)) {
                    debugging('During upgrade, detected that questions ' . implode(', ', array_values($questionidtoslotrowid)) . ' had instances in quiz ' . $quiz->id . ' but were not actually used. ' . 'The instances have been removed.', DEBUG_NORMAL);
                    $DB->delete_records_list('quiz_slots', 'id', array_keys($questionidtoslotrowid));
                    $problemfound = true;
                }
                // If there were problems found, we probably need to re-compute
                // quiz.sumgrades.
                if ($problemfound) {
                    // C/f the quiz_update_sumgrades function in locallib.php,
                    // but note that what we do here is a bit simpler.
                    $newsumgrades = $DB->get_field_sql("SELECT SUM(maxmark)\n                               FROM {quiz_slots}\n                              WHERE quizid = ?", array($quiz->id));
                    if (!$newsumgrades) {
                        $newsumgrades = 0;
                    }
                    if (abs($newsumgrades - $quiz->sumgrades) > 5.0E-6) {
                        debugging('Because of the previously mentioned problems, ' . 'sumgrades for quiz ' . $quiz->id . ' was changed from ' . $quiz->sumgrades . ' to ' . $newsumgrades . ' You should probably check that this quiz is still working: ' . $CFG->wwwroot . '/mod/quiz/view.php?q=' . $quiz->id . '.', DEBUG_NORMAL);
                        $DB->set_field('quiz', 'sumgrades', $newsumgrades, array('id' => $quiz->id));
                    }
                }
                // Done with this quiz. Update progress bar.
                $numberdone++;
                $pbar->update($numberdone, $numquizzes, "Upgrading quiz structure - {$numberdone}/{$numquizzes}.");
            }
            $transaction->allow_commit();
        }
        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2014022003, 'quiz');
    }
    if ($oldversion < 2014022004) {
        // If, for any reason, there were any quiz_slots missed, then try
        // to do something about that now before we add the NOT NULL constraints.
        // In fact, becuase of the sanity check at the end of the above check,
        // any such quiz_slots rows must refer to a non-existent quiz id, so
        // delete them.
        $DB->delete_records_select('quiz_slots', 'NOT EXISTS (SELECT 1 FROM {quiz} q WHERE q.id = quizid)');
        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2014022004, 'quiz');
        // Now, if any quiz_slots rows are left with slot or page NULL, something
        // is badly wrong.
        if ($DB->record_exists_select('quiz_slots', 'slot IS NULL OR page IS NULL')) {
            throw new coding_exception('Something went wrong in the quiz upgrade step for MDL-43749. ' . 'Some quiz_slots still contain NULLs which will break the NOT NULL constraints we need to add. ' . 'Please report this problem at http://tracker.moodle.org/ so that it can be investigated. Thank you.');
        }
    }
    if ($oldversion < 2014022005) {
        // Changing nullability of field slot on table quiz_slots to not null.
        $table = new xmldb_table('quiz_slots');
        $field = new xmldb_field('slot', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'id');
        // Launch change of nullability for field slot.
        $dbman->change_field_notnull($table, $field);
        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2014022005, 'quiz');
    }
    if ($oldversion < 2014022006) {
        // Changing nullability of field page on table quiz_slots to not null.
        $table = new xmldb_table('quiz_slots');
        $field = new xmldb_field('page', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'quizid');
        // Launch change of nullability for field page.
        $dbman->change_field_notnull($table, $field);
        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2014022006, 'quiz');
    }
    if ($oldversion < 2014022007) {
        // Define index quizid-slot (unique) to be added to quiz_slots.
        $table = new xmldb_table('quiz_slots');
        $index = new xmldb_index('quizid-slot', XMLDB_INDEX_UNIQUE, array('quizid', 'slot'));
        // Conditionally launch add index quizid-slot.
        if (!$dbman->index_exists($table, $index)) {
            $dbman->add_index($table, $index);
        }
        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2014022007, 'quiz');
    }
    if ($oldversion < 2014022008) {
        // Define field questions to be dropped from quiz.
        $table = new xmldb_table('quiz');
        $field = new xmldb_field('questions');
        // Conditionally launch drop field questions.
        if ($dbman->field_exists($table, $field)) {
            $dbman->drop_field($table, $field);
        }
        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2014022008, 'quiz');
    }
    // Moodle v2.7.0 release upgrade line.
    // Put any upgrade step following this.
    if ($oldversion < 2014052800) {
        // Define field completionattemptsexhausted to be added to quiz.
        $table = new xmldb_table('quiz');
        $field = new xmldb_field('completionattemptsexhausted', XMLDB_TYPE_INTEGER, '1', null, null, null, '0', 'showblocks');
        // Conditionally launch add field completionattemptsexhausted.
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }
        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2014052800, 'quiz');
    }
    if ($oldversion < 2014052801) {
        // Define field completionpass to be added to quiz.
        $table = new xmldb_table('quiz');
        $field = new xmldb_field('completionpass', XMLDB_TYPE_INTEGER, '1', null, null, null, 0, 'completionattemptsexhausted');
        // Conditionally launch add field completionpass.
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }
        // Quiz savepoint reached.
        upgrade_mod_savepoint(true, 2014052801, 'quiz');
    }
    // Moodle v2.8.0 release upgrade line.
    // Put any upgrade step following this.
    return true;
}
Beispiel #7
0
    /**
     * Test the group event handlers
     */
    public function test_group_event_handlers() {
        global $DB,$CFG;

        $this->resetAfterTest();

        $this->setAdminUser();

        // Setup course, user and groups

        $course = $this->getDataGenerator()->create_course();
        $user1 = $this->getDataGenerator()->create_user();
        $studentrole = $DB->get_record('role', array('shortname'=>'student'));
        $this->assertNotEmpty($studentrole);
        $this->assertTrue(enrol_try_internal_enrol($course->id, $user1->id, $studentrole->id));
        $group1 = $this->getDataGenerator()->create_group(array('courseid'=>$course->id));
        $group2 = $this->getDataGenerator()->create_group(array('courseid'=>$course->id));
        $this->assertTrue(groups_add_member($group1, $user1));
        $this->assertTrue(groups_add_member($group2, $user1));

        $uniqueid = 0;

        $quiz_generator = $this->getDataGenerator()->get_plugin_generator('mod_quiz');

        $quiz = $quiz_generator->create_instance(array('course'=>$course->id, 'timeclose'=>1200, 'timelimit'=>0));

        // add a group1 override
        $DB->insert_record('quiz_overrides', array('quiz'=>$quiz->id, 'groupid'=>$group1->id, 'timeclose'=>1300, 'timelimit'=>null));

        // add an attempt
        $attemptid = $DB->insert_record('quiz_attempts', array('quiz'=>$quiz->id, 'userid'=>$user1->id, 'state'=>'inprogress', 'timestart'=>100, 'timecheckstate'=>0, 'layout'=>'', 'uniqueid'=>$uniqueid++));

        // update timecheckstate
        quiz_update_open_attempts(array('quizid'=>$quiz->id));
        $this->assertEquals(1300, $DB->get_field('quiz_attempts', 'timecheckstate', array('id'=>$attemptid)));

        // remove from group
        $this->assertTrue(groups_remove_member($group1, $user1));
        $this->assertEquals(1200, $DB->get_field('quiz_attempts', 'timecheckstate', array('id'=>$attemptid)));

        // add back to group
        $this->assertTrue(groups_add_member($group1, $user1));
        $this->assertEquals(1300, $DB->get_field('quiz_attempts', 'timecheckstate', array('id'=>$attemptid)));

        // delete group
        groups_delete_group($group1);
        $this->assertEquals(1200, $DB->get_field('quiz_attempts', 'timecheckstate', array('id'=>$attemptid)));
        $this->assertEquals(0, $DB->count_records('quiz_overrides', array('quiz'=>$quiz->id)));

        // add a group2 override
        $DB->insert_record('quiz_overrides', array('quiz'=>$quiz->id, 'groupid'=>$group2->id, 'timeclose'=>1400, 'timelimit'=>null));
        quiz_update_open_attempts(array('quizid'=>$quiz->id));
        $this->assertEquals(1400, $DB->get_field('quiz_attempts', 'timecheckstate', array('id'=>$attemptid)));

        // delete user1 from all groups
        groups_delete_group_members($course->id, $user1->id);
        $this->assertEquals(1200, $DB->get_field('quiz_attempts', 'timecheckstate', array('id'=>$attemptid)));

        // add back to group2
        $this->assertTrue(groups_add_member($group2, $user1));
        $this->assertEquals(1400, $DB->get_field('quiz_attempts', 'timecheckstate', array('id'=>$attemptid)));

        // delete everyone from all groups
        groups_delete_group_members($course->id);
        $this->assertEquals(1200, $DB->get_field('quiz_attempts', 'timecheckstate', array('id'=>$attemptid)));
    }
Beispiel #8
0
 /**
  * A group member was deleted.
  *
  * @param \core\event\base $event The event.
  * @return void
  */
 public static function group_member_removed($event)
 {
     if (!empty(self::$resetinprogress)) {
         // We will take care of that once the course reset ends.
         return;
     }
     quiz_update_open_attempts(array('userid' => $event->relateduserid, 'groupid' => $event->objectid));
 }