Skip to content

Commit

Permalink
Merge branch 'MDL-32727' of git://github.com/timhunt/moodle
Browse files Browse the repository at this point in the history
Conflicts:
	mod/quiz/db/upgrade.php
Sam Hemelryk committed May 18, 2012

Unverified

No user is associated with the committer email.
2 parents 8225883 + 4267fc5 commit d5e6fe3
Showing 2 changed files with 137 additions and 1 deletion.
137 changes: 136 additions & 1 deletion mod/quiz/db/upgrade.php
Original file line number Diff line number Diff line change
@@ -93,8 +93,143 @@ function xmldb_quiz_upgrade($oldversion) {
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 (get_plugin_list('qtype') as $plugin => $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 quiz-userid-attempt (unique) to be dropped form quiz_attempts.
// 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'));

1 change: 1 addition & 0 deletions question/type/calculated/questiontype.php
Original file line number Diff line number Diff line change
@@ -26,6 +26,7 @@

defined('MOODLE_INTERNAL') || die();

require_once($CFG->dirroot . '/question/type/questionbase.php');
require_once($CFG->dirroot . '/question/type/numerical/question.php');


0 comments on commit d5e6fe3

Please sign in to comment.