MDL-40074 refactoring of quiz code
authorJamie Pratt <me@jamiep.org>
Sat, 6 Jul 2013 06:22:44 +0000 (13:22 +0700)
committerJamie Pratt <me@jamiep.org>
Sun, 14 Jul 2013 09:28:39 +0000 (16:28 +0700)
to reuse code fro quiz attempt walk through

mod/quiz/attemptlib.php
mod/quiz/locallib.php
mod/quiz/startattempt.php

index 2da7835..354407b 100644 (file)
@@ -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;
index fd9a9fb..1d5d881 100644 (file)
@@ -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
index 4a47194..0265221 100644 (file)
@@ -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();