MDL-29627 quiz load access settings when a quiz is being attempted.
authorTim Hunt <T.J.Hunt@open.ac.uk>
Wed, 5 Oct 2011 14:54:57 +0000 (15:54 +0100)
committerTim Hunt <T.J.Hunt@open.ac.uk>
Thu, 13 Oct 2011 10:13:10 +0000 (11:13 +0100)
mod/quiz/accessmanager.php
mod/quiz/attemptlib.php
mod/quiz/startattempt.php
mod/quiz/view.php

index 5217178..2d2cd3c 100644 (file)
@@ -124,23 +124,16 @@ class quiz_access_manager {
     }
 
     /**
-     * Load any settings required by the access rules. We try to do this with
-     * a single DB query.
-     *
-     * Note that the standard plugins do not use this mechanism, becuase all their
-     * settings are stored in the quiz table.
-     *
+     * Build the SQL for loading all the access settings in one go.
      * @param int $quizid the quiz id.
-     * @return array setting value name => value. The value names should all
-     *      start with the name of the corresponding plugin to avoid collisions.
+     * @param string $basefields initial part of the select list.
+     * @return array with two elements, the sql and the placeholder values.
      */
-    public static function load_settings($quizid) {
-        global $DB;
-        $rules = get_plugin_list_with_class('quizaccess', '', 'rule.php');
-
-        $allfields = '';
+    protected static function get_load_sql($quizid, $rules, $basefields) {
+        $allfields = $basefields;
         $alljoins = '{quiz} quiz';
         $allparams = array('quizid' => $quizid);
+
         foreach ($rules as $rule) {
             list($fields, $joins, $params) = $rule::get_settings_sql($quizid);
             if ($fields) {
@@ -156,10 +149,27 @@ class quiz_access_manager {
                 $allparams += $params;
             }
         }
-        $data = (array) $DB->get_record_sql("
-                SELECT $allfields
-                  FROM $alljoins
-                 WHERE quiz.id = :quizid", $allparams);
+
+        return array("SELECT $allfields FROM $alljoins WHERE quiz.id = :quizid", $allparams);
+    }
+
+    /**
+     * Load any settings required by the access rules. We try to do this with
+     * a single DB query.
+     *
+     * Note that the standard plugins do not use this mechanism, becuase all their
+     * settings are stored in the quiz table.
+     *
+     * @param int $quizid the quiz id.
+     * @return array setting value name => value. The value names should all
+     *      start with the name of the corresponding plugin to avoid collisions.
+     */
+    public static function load_settings($quizid) {
+        global $DB;
+
+        $rules = get_plugin_list_with_class('quizaccess', '', 'rule.php');
+        list($sql, $params) = self::get_load_sql($quizid, $rules, '');
+        $data = (array) $DB->get_record_sql($sql, $params);
 
         foreach ($rules as $rule) {
             $data += $rule::get_extra_settings($quizid);
@@ -168,6 +178,32 @@ class quiz_access_manager {
         return $data;
     }
 
+    /**
+     * Load the quiz settings and any settings required by the access rules.
+     * We try to do this with a single DB query.
+     *
+     * Note that the standard plugins do not use this mechanism, becuase all their
+     * settings are stored in the quiz table.
+     *
+     * @param int $quizid the quiz id.
+     * @return object mdl_quiz row with extra fields.
+     */
+    public static function load_quiz_and_settings($quizid) {
+        global $DB;
+
+        $rules = get_plugin_list_with_class('quizaccess', '', 'rule.php');
+        list($sql, $params) = self::get_load_sql($quizid, $rules, 'quiz.*');
+        $quiz = $DB->get_record_sql($sql, $params, MUST_EXIST);
+
+        foreach ($rules as $rule) {
+            foreach ($rule::get_extra_settings($quizid) as $name => $value) {
+                $quiz->$name = $value;
+            }
+        }
+
+        return $quiz;
+    }
+
     protected function accumulate_messages(&$messages, $new) {
         if (is_array($new)) {
             $messages = array_merge($messages, $new);
index 98f4daf..af99b63 100644 (file)
@@ -103,7 +103,7 @@ class quiz {
     public static function create($quizid, $userid) {
         global $DB;
 
-        $quiz = $DB->get_record('quiz', array('id' => $quizid), '*', MUST_EXIST);
+        $quiz = quiz_access_manager::load_quiz_and_settings($quizid);
         $course = $DB->get_record('course', array('id' => $quiz->course), '*', MUST_EXIST);
         $cm = get_coursemodule_from_instance('quiz', $quiz->id, $course->id, false, MUST_EXIST);
 
@@ -383,7 +383,7 @@ class quiz_attempt {
         global $DB;
 
         $attempt = $DB->get_record('quiz_attempts', $conditions, '*', MUST_EXIST);
-        $quiz = $DB->get_record('quiz', array('id' => $attempt->quiz), '*', MUST_EXIST);
+        $quiz = quiz_access_manager::load_quiz_and_settings($attempt->quiz);
         $course = $DB->get_record('course', array('id' => $quiz->course), '*', MUST_EXIST);
         $cm = get_coursemodule_from_instance('quiz', $quiz->id, $course->id, false, MUST_EXIST);
 
index 4f85d37..1323220 100644 (file)
@@ -41,11 +41,8 @@ if (!$cm = get_coursemodule_from_id('quiz', $id)) {
 if (!$course = $DB->get_record('course', array('id' => $cm->course))) {
     print_error("coursemisconf");
 }
-if (!$quiz = $DB->get_record('quiz', array('id' => $cm->instance))) {
-    print_error('invalidcoursemodule');
-}
 
-$quizobj = quiz::create($quiz->id, $USER->id);
+$quizobj = quiz::create($cm->instance, $USER->id);
 // This script should only ever be posted to, so set page URL to the view page.
 $PAGE->set_url($quizobj->view_url());
 
@@ -75,11 +72,11 @@ if ($quizobj->is_preview_user() && $forcenew) {
     // To force the creation of a new preview, we set a finish time on the
     // current attempt (if any). It will then automatically be deleted below
     $DB->set_field('quiz_attempts', 'timefinish', time(),
-            array('quiz' => $quiz->id, 'userid' => $USER->id));
+            array('quiz' => $quizobj->get_quizid(), 'userid' => $USER->id));
 }
 
 // Look for an existing attempt.
-$attempts = quiz_get_user_attempts($quiz->id, $USER->id, 'all');
+$attempts = quiz_get_user_attempts($quizobj->get_quizid(), $USER->id, 'all');
 $lastattempt = end($attempts);
 
 // If an in-progress attempt exists, check password then redirect to it.
@@ -107,16 +104,16 @@ if (!$quizobj->is_preview_user() && $messages) {
 $accessmanager->do_password_check($quizobj->is_preview_user());
 
 // Delete any previous preview attempts belonging to this user.
-quiz_delete_previews($quiz, $USER->id);
+quiz_delete_previews($quizobj->get_quiz(), $USER->id);
 
 $quba = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context());
-$quba->set_preferred_behaviour($quiz->preferredbehaviour);
+$quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour);
 
 // Create the new attempt and initialize the question sessions
-$attempt = quiz_create_attempt($quiz, $attemptnumber, $lastattempt, time(),
+$attempt = quiz_create_attempt($quizobj->get_quiz(), $attemptnumber, $lastattempt, time(),
         $quizobj->is_preview_user());
 
-if (!($quiz->attemptonlast && $lastattempt)) {
+if (!($quizobj->get_quiz()->attemptonlast && $lastattempt)) {
     // Starting a normal, new, quiz attempt.
 
     // Fully load all the questions in this quiz.
@@ -128,14 +125,14 @@ if (!($quiz->attemptonlast && $lastattempt)) {
     $questionsinuse = array_keys($quizobj->get_questions());
     foreach ($quizobj->get_questions() as $i => $questiondata) {
         if ($questiondata->qtype != 'random') {
-            if (!$quiz->shuffleanswers) {
+            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, $quiz->shuffleanswers);
+                    $questiondata, $questionsinuse, $quizobj->get_quiz()->shuffleanswers);
             if (is_null($question)) {
                 throw new moodle_exception('notenoughrandomquestions', 'quiz',
                         $quizobj->view_url(), $questiondata);
index 642e8bf..c38b8d5 100644 (file)
@@ -40,9 +40,6 @@ if ($id) {
     if (!$course = $DB->get_record('course', array('id' => $cm->course))) {
         print_error('coursemisconf');
     }
-    if (!$quiz = $DB->get_record('quiz', array('id' => $cm->instance))) {
-        print_error('invalidcoursemodule');
-    }
 } else {
     if (!$quiz = $DB->get_record('quiz', array('id' => $q))) {
         print_error('invalidquizid', 'quiz');
@@ -67,8 +64,10 @@ $canpreview = has_capability('mod/quiz:preview', $context);
 
 // Create an object to manage all the other (non-roles) access rules.
 $timenow = time();
-$accessmanager = new quiz_access_manager(quiz::create($quiz->id, $USER->id), $timenow,
+$quizobj = quiz::create($cm->instance, $USER->id);
+$accessmanager = new quiz_access_manager($quizobj, $timenow,
         has_capability('mod/quiz:ignoretimelimits', $context, null, false));
+$quiz = $quizobj->get_quiz();
 
 // Log this request.
 add_to_log($course->id, 'quiz', 'view', 'view.php?id=' . $cm->id, $quiz->id, $cm->id);
@@ -84,9 +83,6 @@ if ($edit != -1 && $PAGE->user_allowed_editing()) {
     $USER->editing = $edit;
 }
 
-// Update the quiz with overrides for the current user
-$quiz = quiz_update_effective_access($quiz, $USER->id);
-
 // Get this user's attempts.
 $attempts = quiz_get_user_attempts($quiz->id, $USER->id, 'finished', true);
 $lastfinishedattempt = end($attempts);