Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/mod/quiz/startattempt.php
Go to the documentation of this file.
00001 <?php
00002 // This file is part of Moodle - http://moodle.org/
00003 //
00004 // Moodle is free software: you can redistribute it and/or modify
00005 // it under the terms of the GNU General Public License as published by
00006 // the Free Software Foundation, either version 3 of the License, or
00007 // (at your option) any later version.
00008 //
00009 // Moodle is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
00016 
00030 require_once(dirname(__FILE__) . '/../../config.php');
00031 require_once($CFG->dirroot . '/mod/quiz/locallib.php');
00032 
00033 // Get submitted parameters.
00034 $id = required_param('cmid', PARAM_INT); // Course module id
00035 $forcenew = optional_param('forcenew', false, PARAM_BOOL); // Used to force a new preview
00036 $page = optional_param('page', 0, PARAM_INT); // Page to jump to in the attempt.
00037 
00038 if (!$cm = get_coursemodule_from_id('quiz', $id)) {
00039     print_error('invalidcoursemodule');
00040 }
00041 if (!$course = $DB->get_record('course', array('id' => $cm->course))) {
00042     print_error("coursemisconf");
00043 }
00044 
00045 $quizobj = quiz::create($cm->instance, $USER->id);
00046 // This script should only ever be posted to, so set page URL to the view page.
00047 $PAGE->set_url($quizobj->view_url());
00048 
00049 // Check login and sesskey.
00050 require_login($quizobj->get_courseid(), false, $quizobj->get_cm());
00051 require_sesskey();
00052 
00053 // if no questions have been set up yet redirect to edit.php or display an error.
00054 if (!$quizobj->has_questions()) {
00055     if ($quizobj->has_capability('mod/quiz:manage')) {
00056         redirect($quizobj->edit_url());
00057     } else {
00058         print_error('cannotstartnoquestions', 'quiz', $quizobj->view_url());
00059     }
00060 }
00061 
00062 // Create an object to manage all the other (non-roles) access rules.
00063 $accessmanager = $quizobj->get_access_manager(time());
00064 if ($quizobj->is_preview_user() && $forcenew) {
00065     $accessmanager->current_attempt_finished();
00066 }
00067 
00068 // Check capabilities.
00069 if (!$quizobj->is_preview_user()) {
00070     $quizobj->require_capability('mod/quiz:attempt');
00071 }
00072 
00073 // Check to see if a new preview was requested.
00074 if ($quizobj->is_preview_user() && $forcenew) {
00075     // To force the creation of a new preview, we set a finish time on the
00076     // current attempt (if any). It will then automatically be deleted below
00077     $DB->set_field('quiz_attempts', 'timefinish', time(),
00078             array('quiz' => $quizobj->get_quizid(), 'userid' => $USER->id));
00079 }
00080 
00081 // Look for an existing attempt.
00082 $attempts = quiz_get_user_attempts($quizobj->get_quizid(), $USER->id, 'all', true);
00083 $lastattempt = end($attempts);
00084 
00085 // If an in-progress attempt exists, check password then redirect to it.
00086 if ($lastattempt && !$lastattempt->timefinish) {
00087     $currentattemptid = $lastattempt->id;
00088     $messages = $accessmanager->prevent_access();
00089 
00090 } else {
00091     // Get number for the next or unfinished attempt
00092     if ($lastattempt && !$lastattempt->preview && !$quizobj->is_preview_user()) {
00093         $attemptnumber = $lastattempt->attempt + 1;
00094     } else {
00095         $lastattempt = false;
00096         $attemptnumber = 1;
00097     }
00098     $currentattemptid = null;
00099 
00100     $messages = $accessmanager->prevent_access() +
00101             $accessmanager->prevent_new_attempt(count($attempts), $lastattempt);
00102 }
00103 
00104 // Check access.
00105 $output = $PAGE->get_renderer('mod_quiz');
00106 if (!$quizobj->is_preview_user() && $messages) {
00107     print_error('attempterror', 'quiz', $quizobj->view_url(),
00108             $output->access_messages($messages));
00109 }
00110 
00111 if ($accessmanager->is_preflight_check_required($currentattemptid)) {
00112     // Need to do some checks before allowing the user to continue.
00113     $mform = $accessmanager->get_preflight_check_form(
00114             $quizobj->start_attempt_url($page), $currentattemptid);
00115 
00116     if ($mform->is_cancelled()) {
00117         $accessmanager->back_to_view_page($output);
00118 
00119     } else if (!$mform->get_data()) {
00120 
00121         // Form not submitted successfully, re-display it and stop.
00122         $PAGE->set_url($quizobj->start_attempt_url($page));
00123         $PAGE->set_title(format_string($quizobj->get_quiz_name()));
00124         $accessmanager->setup_attempt_page($PAGE);
00125         if (empty($quizobj->get_quiz()->showblocks)) {
00126             $PAGE->blocks->show_only_fake_blocks();
00127         }
00128 
00129         echo $output->start_attempt_page($quizobj, $mform);
00130         die();
00131     }
00132 
00133     // Pre-flight check passed.
00134     $accessmanager->notify_preflight_check_passed($currentattemptid);
00135 }
00136 if ($currentattemptid) {
00137     redirect($quizobj->attempt_url($currentattemptid, $page));
00138 }
00139 
00140 // Delete any previous preview attempts belonging to this user.
00141 quiz_delete_previews($quizobj->get_quiz(), $USER->id);
00142 
00143 $quba = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context());
00144 $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour);
00145 
00146 // Create the new attempt and initialize the question sessions
00147 $attempt = quiz_create_attempt($quizobj->get_quiz(), $attemptnumber, $lastattempt, time(),
00148         $quizobj->is_preview_user());
00149 
00150 if (!($quizobj->get_quiz()->attemptonlast && $lastattempt)) {
00151     // Starting a normal, new, quiz attempt.
00152 
00153     // Fully load all the questions in this quiz.
00154     $quizobj->preload_questions();
00155     $quizobj->load_questions();
00156 
00157     // Add them all to the $quba.
00158     $idstoslots = array();
00159     $questionsinuse = array_keys($quizobj->get_questions());
00160     foreach ($quizobj->get_questions() as $i => $questiondata) {
00161         if ($questiondata->qtype != 'random') {
00162             if (!$quizobj->get_quiz()->shuffleanswers) {
00163                 $questiondata->options->shuffleanswers = false;
00164             }
00165             $question = question_bank::make_question($questiondata);
00166 
00167         } else {
00168             $question = question_bank::get_qtype('random')->choose_other_question(
00169                     $questiondata, $questionsinuse, $quizobj->get_quiz()->shuffleanswers);
00170             if (is_null($question)) {
00171                 throw new moodle_exception('notenoughrandomquestions', 'quiz',
00172                         $quizobj->view_url(), $questiondata);
00173             }
00174         }
00175 
00176         $idstoslots[$i] = $quba->add_question($question, $questiondata->maxmark);
00177         $questionsinuse[] = $question->id;
00178     }
00179 
00180     // Start all the questions.
00181     if ($attempt->preview) {
00182         $variantoffset = rand(1, 100);
00183     } else {
00184         $variantoffset = $attemptnumber;
00185     }
00186     $quba->start_all_questions(
00187             new question_variant_pseudorandom_no_repeats_strategy($variantoffset),
00188             time());
00189 
00190     // Update attempt layout.
00191     $newlayout = array();
00192     foreach (explode(',', $attempt->layout) as $qid) {
00193         if ($qid != 0) {
00194             $newlayout[] = $idstoslots[$qid];
00195         } else {
00196             $newlayout[] = 0;
00197         }
00198     }
00199     $attempt->layout = implode(',', $newlayout);
00200 
00201 } else {
00202     // Starting a subsequent attempt in each attempt builds on last mode.
00203 
00204     $oldquba = question_engine::load_questions_usage_by_activity($lastattempt->uniqueid);
00205 
00206     $oldnumberstonew = array();
00207     foreach ($oldquba->get_attempt_iterator() as $oldslot => $oldqa) {
00208         $newslot = $quba->add_question($oldqa->get_question(), $oldqa->get_max_mark());
00209 
00210         $quba->start_question_based_on($newslot, $oldqa);
00211 
00212         $oldnumberstonew[$oldslot] = $newslot;
00213     }
00214 
00215     // Update attempt layout.
00216     $newlayout = array();
00217     foreach (explode(',', $lastattempt->layout) as $oldslot) {
00218         if ($oldslot != 0) {
00219             $newlayout[] = $oldnumberstonew[$oldslot];
00220         } else {
00221             $newlayout[] = 0;
00222         }
00223     }
00224     $attempt->layout = implode(',', $newlayout);
00225 }
00226 
00227 // Save the attempt in the database.
00228 $transaction = $DB->start_delegated_transaction();
00229 question_engine::save_questions_usage_by_activity($quba);
00230 $attempt->uniqueid = $quba->get_id();
00231 $attempt->id = $DB->insert_record('quiz_attempts', $attempt);
00232 
00233 // Log the new attempt.
00234 if ($attempt->preview) {
00235     add_to_log($course->id, 'quiz', 'preview', 'view.php?id=' . $quizobj->get_cmid(),
00236             $quizobj->get_quizid(), $quizobj->get_cmid());
00237 } else {
00238     add_to_log($course->id, 'quiz', 'attempt', 'review.php?attempt=' . $attempt->id,
00239             $quizobj->get_quizid(), $quizobj->get_cmid());
00240 }
00241 
00242 // Trigger event
00243 $eventdata = new stdClass();
00244 $eventdata->component = 'mod_quiz';
00245 $eventdata->attemptid = $attempt->id;
00246 $eventdata->timestart = $attempt->timestart;
00247 $eventdata->userid    = $attempt->userid;
00248 $eventdata->quizid    = $quizobj->get_quizid();
00249 $eventdata->cmid      = $quizobj->get_cmid();
00250 $eventdata->courseid  = $quizobj->get_courseid();
00251 events_trigger('quiz_attempt_started', $eventdata);
00252 
00253 $transaction->allow_commit();
00254 
00255 // Redirect to the attempt page.
00256 redirect($quizobj->attempt_url($attempt->id, $page));
 All Data Structures Namespaces Files Functions Variables Enumerations