mirror of
https://github.com/moodle/moodle.git
synced 2025-04-14 13:02:07 +02:00
MDL-40074 refactoring of quiz code
to reuse code fro quiz attempt walk through
This commit is contained in:
parent
07bbbcf174
commit
1cd7c92ece
@ -1333,12 +1333,12 @@ class quiz_attempt {
|
||||
* @param int $timestamp the timestamp that should be stored as the modifed
|
||||
* time in the database for these actions. If null, will use the current time.
|
||||
*/
|
||||
public function process_submitted_actions($timestamp, $becomingoverdue = false) {
|
||||
public function process_submitted_actions($timestamp, $becomingoverdue = false, $postdata = null) {
|
||||
global $DB;
|
||||
|
||||
$transaction = $DB->start_delegated_transaction();
|
||||
|
||||
$this->quba->process_all_actions($timestamp);
|
||||
$this->quba->process_all_actions($timestamp, $postdata);
|
||||
question_engine::save_questions_usage_by_activity($this->quba);
|
||||
|
||||
$this->attempt->timemodified = $timestamp;
|
||||
|
@ -137,6 +137,145 @@ function quiz_create_attempt(quiz $quizobj, $attemptnumber, $lastattempt, $timen
|
||||
|
||||
return $attempt;
|
||||
}
|
||||
/**
|
||||
* Start a normal, new, quiz attempt.
|
||||
*
|
||||
* @param quiz $quizobj the quiz object to start an attempt for.
|
||||
* @param question_usage_by_activity $quba
|
||||
* @param object $attempt
|
||||
* @param integer $attemptnumber starting from 1
|
||||
* @param integer $timenow the attempt start time
|
||||
* @return object modified attempt object
|
||||
* @throws moodle_exception if a random question exhausts the available questions
|
||||
*/
|
||||
function quiz_start_new_attempt($quizobj, $quba, $attempt, $attemptnumber, $timenow) {
|
||||
// Fully load all the questions in this quiz.
|
||||
$quizobj->preload_questions();
|
||||
$quizobj->load_questions();
|
||||
|
||||
// Add them all to the $quba.
|
||||
$idstoslots = array();
|
||||
$questionsinuse = array_keys($quizobj->get_questions());
|
||||
foreach ($quizobj->get_questions() as $i => $questiondata) {
|
||||
if ($questiondata->qtype != 'random') {
|
||||
if (!$quizobj->get_quiz()->shuffleanswers) {
|
||||
$questiondata->options->shuffleanswers = false;
|
||||
}
|
||||
$question = question_bank::make_question($questiondata);
|
||||
|
||||
} else {
|
||||
$question = question_bank::get_qtype('random')->choose_other_question(
|
||||
$questiondata, $questionsinuse, $quizobj->get_quiz()->shuffleanswers);
|
||||
if (is_null($question)) {
|
||||
throw new moodle_exception('notenoughrandomquestions', 'quiz',
|
||||
$quizobj->view_url(), $questiondata);
|
||||
}
|
||||
}
|
||||
|
||||
$idstoslots[$i] = $quba->add_question($question, $questiondata->maxmark);
|
||||
$questionsinuse[] = $question->id;
|
||||
}
|
||||
|
||||
// Start all the questions.
|
||||
if ($attempt->preview) {
|
||||
$variantoffset = rand(1, 100);
|
||||
} else {
|
||||
$variantoffset = $attemptnumber;
|
||||
}
|
||||
$quba->start_all_questions(
|
||||
new question_variant_pseudorandom_no_repeats_strategy($variantoffset), $timenow);
|
||||
|
||||
// Update attempt layout.
|
||||
$newlayout = array();
|
||||
foreach (explode(',', $attempt->layout) as $qid) {
|
||||
if ($qid != 0) {
|
||||
$newlayout[] = $idstoslots[$qid];
|
||||
} else {
|
||||
$newlayout[] = 0;
|
||||
}
|
||||
}
|
||||
$attempt->layout = implode(',', $newlayout);
|
||||
return $attempt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a subsequent new attempt, in each attempt builds on last mode.
|
||||
*
|
||||
* @param question_usage_by_activity $quba this question usage
|
||||
* @param object $attempt this attempt
|
||||
* @param object $lastattempt last attempt
|
||||
* @return object modified attempt object
|
||||
*
|
||||
*/
|
||||
function quiz_start_attempt_built_on_last($quba, $attempt, $lastattempt) {
|
||||
$oldquba = question_engine::load_questions_usage_by_activity($lastattempt->uniqueid);
|
||||
|
||||
$oldnumberstonew = array();
|
||||
foreach ($oldquba->get_attempt_iterator() as $oldslot => $oldqa) {
|
||||
$newslot = $quba->add_question($oldqa->get_question(), $oldqa->get_max_mark());
|
||||
|
||||
$quba->start_question_based_on($newslot, $oldqa);
|
||||
|
||||
$oldnumberstonew[$oldslot] = $newslot;
|
||||
}
|
||||
|
||||
// Update attempt layout.
|
||||
$newlayout = array();
|
||||
foreach (explode(',', $lastattempt->layout) as $oldslot) {
|
||||
if ($oldslot != 0) {
|
||||
$newlayout[] = $oldnumberstonew[$oldslot];
|
||||
} else {
|
||||
$newlayout[] = 0;
|
||||
}
|
||||
}
|
||||
$attempt->layout = implode(',', $newlayout);
|
||||
return $attempt;
|
||||
}
|
||||
|
||||
/**
|
||||
* The save started question usage and quiz attempt in db and log the started attempt.
|
||||
*
|
||||
* @param quiz $quizobj
|
||||
* @param question_usage_by_activity $quba
|
||||
* @param object $attempt
|
||||
* @return object attempt object with uniqueid and id set.
|
||||
*/
|
||||
function quiz_attempt_save_started($quizobj, $quba, $attempt) {
|
||||
global $DB;
|
||||
// Save the attempt in the database.
|
||||
question_engine::save_questions_usage_by_activity($quba);
|
||||
$attempt->uniqueid = $quba->get_id();
|
||||
$attempt->id = $DB->insert_record('quiz_attempts', $attempt);
|
||||
// Log the new attempt.
|
||||
if ($attempt->preview) {
|
||||
add_to_log($quizobj->get_courseid(), 'quiz', 'preview', 'view.php?id='.$quizobj->get_cmid(),
|
||||
$quizobj->get_quizid(), $quizobj->get_cmid());
|
||||
} else {
|
||||
add_to_log($quizobj->get_courseid(), 'quiz', 'attempt', 'review.php?attempt='.$attempt->id,
|
||||
$quizobj->get_quizid(), $quizobj->get_cmid());
|
||||
}
|
||||
return $attempt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire an event to tell the rest of Moodle a quiz attempt has started.
|
||||
*
|
||||
* @param object $attempt
|
||||
* @param quiz $quizobj
|
||||
*/
|
||||
function quiz_fire_attempt_started_event($attempt, $quizobj) {
|
||||
// Trigger event.
|
||||
$eventdata = new stdClass();
|
||||
$eventdata->component = 'mod_quiz';
|
||||
$eventdata->attemptid = $attempt->id;
|
||||
$eventdata->timestart = $attempt->timestart;
|
||||
$eventdata->timestamp = $attempt->timestart;
|
||||
$eventdata->userid = $attempt->userid;
|
||||
$eventdata->quizid = $quizobj->get_quizid();
|
||||
$eventdata->cmid = $quizobj->get_cmid();
|
||||
$eventdata->courseid = $quizobj->get_courseid();
|
||||
events_trigger('quiz_attempt_started', $eventdata);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an unfinished attempt (if there is one) for the given
|
||||
|
@ -169,111 +169,18 @@ $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour);
|
||||
|
||||
// Create the new attempt and initialize the question sessions
|
||||
$timenow = time(); // Update time now, in case the server is running really slowly.
|
||||
$attempt = quiz_create_attempt($quizobj, $attemptnumber, $lastattempt, $timenow,
|
||||
$quizobj->is_preview_user());
|
||||
$attempt = quiz_create_attempt($quizobj, $attemptnumber, $lastattempt, $timenow, $quizobj->is_preview_user());
|
||||
|
||||
if (!($quizobj->get_quiz()->attemptonlast && $lastattempt)) {
|
||||
// Starting a normal, new, quiz attempt.
|
||||
|
||||
// Fully load all the questions in this quiz.
|
||||
$quizobj->preload_questions();
|
||||
$quizobj->load_questions();
|
||||
|
||||
// Add them all to the $quba.
|
||||
$idstoslots = array();
|
||||
$questionsinuse = array_keys($quizobj->get_questions());
|
||||
foreach ($quizobj->get_questions() as $i => $questiondata) {
|
||||
if ($questiondata->qtype != 'random') {
|
||||
if (!$quizobj->get_quiz()->shuffleanswers) {
|
||||
$questiondata->options->shuffleanswers = false;
|
||||
}
|
||||
$question = question_bank::make_question($questiondata);
|
||||
|
||||
} else {
|
||||
$question = question_bank::get_qtype('random')->choose_other_question(
|
||||
$questiondata, $questionsinuse, $quizobj->get_quiz()->shuffleanswers);
|
||||
if (is_null($question)) {
|
||||
throw new moodle_exception('notenoughrandomquestions', 'quiz',
|
||||
$quizobj->view_url(), $questiondata);
|
||||
}
|
||||
}
|
||||
|
||||
$idstoslots[$i] = $quba->add_question($question, $questiondata->maxmark);
|
||||
$questionsinuse[] = $question->id;
|
||||
}
|
||||
|
||||
// Start all the questions.
|
||||
if ($attempt->preview) {
|
||||
$variantoffset = rand(1, 100);
|
||||
} else {
|
||||
$variantoffset = $attemptnumber;
|
||||
}
|
||||
$quba->start_all_questions(
|
||||
new question_variant_pseudorandom_no_repeats_strategy($variantoffset), $timenow);
|
||||
|
||||
// Update attempt layout.
|
||||
$newlayout = array();
|
||||
foreach (explode(',', $attempt->layout) as $qid) {
|
||||
if ($qid != 0) {
|
||||
$newlayout[] = $idstoslots[$qid];
|
||||
} else {
|
||||
$newlayout[] = 0;
|
||||
}
|
||||
}
|
||||
$attempt->layout = implode(',', $newlayout);
|
||||
|
||||
$attempt = quiz_start_new_attempt($quizobj, $quba, $attempt, $attemptnumber, $timenow);
|
||||
} else {
|
||||
// Starting a subsequent attempt in each attempt builds on last mode.
|
||||
|
||||
$oldquba = question_engine::load_questions_usage_by_activity($lastattempt->uniqueid);
|
||||
|
||||
$oldnumberstonew = array();
|
||||
foreach ($oldquba->get_attempt_iterator() as $oldslot => $oldqa) {
|
||||
$newslot = $quba->add_question($oldqa->get_question(), $oldqa->get_max_mark());
|
||||
|
||||
$quba->start_question_based_on($newslot, $oldqa);
|
||||
|
||||
$oldnumberstonew[$oldslot] = $newslot;
|
||||
}
|
||||
|
||||
// Update attempt layout.
|
||||
$newlayout = array();
|
||||
foreach (explode(',', $lastattempt->layout) as $oldslot) {
|
||||
if ($oldslot != 0) {
|
||||
$newlayout[] = $oldnumberstonew[$oldslot];
|
||||
} else {
|
||||
$newlayout[] = 0;
|
||||
}
|
||||
}
|
||||
$attempt->layout = implode(',', $newlayout);
|
||||
$attempt = quiz_start_attempt_built_on_last($quba, $attempt, $lastattempt);
|
||||
}
|
||||
|
||||
// Save the attempt in the database.
|
||||
$transaction = $DB->start_delegated_transaction();
|
||||
question_engine::save_questions_usage_by_activity($quba);
|
||||
$attempt->uniqueid = $quba->get_id();
|
||||
$attempt->id = $DB->insert_record('quiz_attempts', $attempt);
|
||||
|
||||
// Log the new attempt.
|
||||
if ($attempt->preview) {
|
||||
add_to_log($course->id, 'quiz', 'preview', 'view.php?id=' . $quizobj->get_cmid(),
|
||||
$quizobj->get_quizid(), $quizobj->get_cmid());
|
||||
} else {
|
||||
add_to_log($course->id, 'quiz', 'attempt', 'review.php?attempt=' . $attempt->id,
|
||||
$quizobj->get_quizid(), $quizobj->get_cmid());
|
||||
}
|
||||
|
||||
// Trigger event.
|
||||
$eventdata = new stdClass();
|
||||
$eventdata->component = 'mod_quiz';
|
||||
$eventdata->attemptid = $attempt->id;
|
||||
$eventdata->timestart = $attempt->timestart;
|
||||
$eventdata->timestamp = $attempt->timestart;
|
||||
$eventdata->userid = $attempt->userid;
|
||||
$eventdata->quizid = $quizobj->get_quizid();
|
||||
$eventdata->cmid = $quizobj->get_cmid();
|
||||
$eventdata->courseid = $quizobj->get_courseid();
|
||||
events_trigger('quiz_attempt_started', $eventdata);
|
||||
$attempt = quiz_attempt_save_started($quizobj, $quba, $attempt);
|
||||
quiz_fire_attempt_started_event($attempt, $quizobj);
|
||||
|
||||
$transaction->allow_commit();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user