// Get submitted parameters.
$attemptid = required_param('attempt', PARAM_INT);
$page = optional_param('page', 0, PARAM_INT);
+$cmid = optional_param('cmid', null, PARAM_INT);
-$attemptobj = quiz_attempt::create($attemptid);
+$attemptobj = quiz_create_attempt_handling_errors($attemptid, $cmid);
$page = $attemptobj->force_page_number_into_range($page);
$PAGE->set_url($attemptobj->attempt_url(null, $page));
if ($page) {
$url .= '&page=' . $page;
}
+ $url .= '&cmid=' . $this->get_cmid();
return $url;
}
* @return string the URL of the review of that attempt.
*/
public function review_url($attemptid) {
- return new moodle_url('/mod/quiz/review.php', array('attempt' => $attemptid));
+ return new moodle_url('/mod/quiz/review.php', array('attempt' => $attemptid, 'cmid' => $this->get_cmid()));
}
/**
* @return string the URL of the review of that attempt.
*/
public function summary_url($attemptid) {
- return new moodle_url('/mod/quiz/summary.php', array('attempt' => $attemptid));
+ return new moodle_url('/mod/quiz/summary.php', array('attempt' => $attemptid, 'cmid' => $this->get_cmid()));
}
// Bits of content =========================================================
* @return string the URL of this quiz's summary page.
*/
public function summary_url() {
- return new moodle_url('/mod/quiz/summary.php', array('attempt' => $this->attempt->id));
+ return new moodle_url('/mod/quiz/summary.php', array('attempt' => $this->attempt->id, 'cmid' => $this->get_cmid()));
}
/**
} else {
$url = new moodle_url('/mod/quiz/' . $script . '.php' . $fragment,
- array('attempt' => $this->attempt->id));
+ array('attempt' => $this->attempt->id, 'cmid' => $this->get_cmid()));
if ($page == 0 && $showall != $defaultshowall) {
$url->param('showall', (int) $showall);
} else if ($page > 0) {
// Get submitted parameters.
$attemptid = required_param('attempt', PARAM_INT);
$thispage = optional_param('thispage', 0, PARAM_INT);
+$cmid = optional_param('cmid', null, PARAM_INT);
$transaction = $DB->start_delegated_transaction();
-$attemptobj = quiz_attempt::create($attemptid);
+$attemptobj = quiz_create_attempt_handling_errors($attemptid, $cmid);
// Check login.
require_login($attemptobj->get_course(), false, $attemptobj->get_cm());
$attemptid = required_param('attempt', PARAM_INT);
$slot = required_param('slot', PARAM_INT); // The question number in the attempt.
+$cmid = optional_param('cmid', null, PARAM_INT);
$PAGE->set_url('/mod/quiz/comment.php', array('attempt' => $attemptid, 'slot' => $slot));
-$attemptobj = quiz_attempt::create($attemptid);
+$attemptobj = quiz_create_attempt_handling_errors($attemptid, $cmid);
$student = $DB->get_record('user', array('id' => $attemptobj->get_userid()));
// Can only grade finished attempts.
$string['attemptduration'] = 'Time taken';
$string['attemptedon'] = 'Attempted on';
$string['attempterror'] = 'You are not allowed to attempt this quiz at this time because: {$a}';
+$string['attempterrorinvalid'] = 'Invalid quiz attempt ID';
+$string['attempterrorcontentchange'] = 'This quiz attempt no longer exists. (When a quiz is edited in-progress previews are automatically deleted.)';
+$string['attempterrorcontentchangeforuser'] = 'This quiz attempt no longer exists.';
$string['attemptfirst'] = 'First attempt';
$string['attemptincomplete'] = 'That attempt (by {$a}) is not yet completed.';
$string['attemptlast'] = 'Last attempt';
// Only work with tags that exist.
return array_filter(array_column($tags, 'id'));
-}
\ No newline at end of file
+}
+
+/**
+ * Get quiz attempt and handling error.
+ *
+ * @param int $attemptid the id of the current attempt.
+ * @param int|null $cmid the course_module id for this quiz.
+ * @return quiz_attempt $attemptobj all the data about the quiz attempt.
+ * @throws moodle_exception
+ */
+function quiz_create_attempt_handling_errors($attemptid, $cmid = null) {
+ try {
+ $attempobj = quiz_attempt::create($attemptid);
+ } catch (moodle_exception $e) {
+ if (!empty($cmid)) {
+ list($course, $cm) = get_course_and_cm_from_cmid($cmid, 'quiz');
+ $continuelink = new moodle_url('/mod/quiz/view.php', array('id' => $cmid));
+ $context = context_module::instance($cm->id);
+ if (has_capability('mod/quiz:preview', $context)) {
+ throw new moodle_exception('attempterrorcontentchange', 'quiz', $continuelink);
+ } else {
+ throw new moodle_exception('attempterrorcontentchangeforuser', 'quiz', $continuelink);
+ }
+ } else {
+ throw new moodle_exception('attempterrorinvalid', 'quiz');
+ }
+ }
+ if (!empty($cmid) && $attempobj->get_cmid() != $cmid) {
+ throw new moodle_exception('invalidcoursemodule');
+ } else {
+ return $attempobj;
+ }
+}
$finishattempt = optional_param('finishattempt', false, PARAM_BOOL);
$timeup = optional_param('timeup', 0, PARAM_BOOL); // True if form was submitted by timer.
$scrollpos = optional_param('scrollpos', '', PARAM_RAW);
+$cmid = optional_param('cmid', null, PARAM_INT);
-$attemptobj = quiz_attempt::create($attemptid);
+$attemptobj = quiz_create_attempt_handling_errors($attemptid, $cmid);
// Set $nexturl now.
if ($next) {
// Start the form.
$output .= html_writer::start_tag('form',
- array('action' => $attemptobj->processattempt_url(), 'method' => 'post',
+ array('action' => new moodle_url($attemptobj->processattempt_url(),
+ array('cmid' => $attemptobj->get_cmid())), 'method' => 'post',
'enctype' => 'multipart/form-data', 'accept-charset' => 'utf-8',
'id' => 'responseform'));
$output .= html_writer::start_tag('div');
'finishattempt' => 1,
'timeup' => 0,
'slots' => '',
+ 'cmid' => $attemptobj->get_cmid(),
'sesskey' => sesskey(),
);
$attemptid = required_param('attempt', PARAM_INT);
$page = optional_param('page', 0, PARAM_INT);
$showall = optional_param('showall', null, PARAM_BOOL);
+$cmid = optional_param('cmid', null, PARAM_INT);
$url = new moodle_url('/mod/quiz/review.php', array('attempt'=>$attemptid));
if ($page !== 0) {
}
$PAGE->set_url($url);
-$attemptobj = quiz_attempt::create($attemptid);
+$attemptobj = quiz_create_attempt_handling_errors($attemptid, $cmid);
$page = $attemptobj->force_page_number_into_range($page);
// Now we can validate the params better, re-genrate the page URL.
$attemptid = required_param('attempt', PARAM_INT);
$slot = required_param('slot', PARAM_INT);
$seq = optional_param('step', null, PARAM_INT);
+$cmid = optional_param('cmid', null, PARAM_INT);
$baseurl = new moodle_url('/mod/quiz/reviewquestion.php',
array('attempt' => $attemptid, 'slot' => $slot));
}
$PAGE->set_url($currenturl);
-$attemptobj = quiz_attempt::create($attemptid);
+$attemptobj = quiz_create_attempt_handling_errors($attemptid, $cmid);
// Check login.
require_login($attemptobj->get_course(), false, $attemptobj->get_cm());
require_once($CFG->dirroot . '/mod/quiz/locallib.php');
$attemptid = required_param('attempt', PARAM_INT); // The attempt to summarise.
+$cmid = optional_param('cmid', null, PARAM_INT);
$PAGE->set_url('/mod/quiz/summary.php', array('attempt' => $attemptid));
-$attemptobj = quiz_attempt::create($attemptid);
+$attemptobj = quiz_create_attempt_handling_errors($attemptid, $cmid);
// Check login.
require_login($attemptobj->get_course(), false, $attemptobj->get_cm());
// Attempt pages.
$this->assertEquals(new moodle_url(
- '/mod/quiz/attempt.php?attempt=123'),
+ '/mod/quiz/attempt.php?attempt=123&cmid=0'),
$attempt->attempt_url());
$this->assertEquals(new moodle_url(
- '/mod/quiz/attempt.php?attempt=123&page=2'),
+ '/mod/quiz/attempt.php?attempt=123&page=2&cmid=0'),
$attempt->attempt_url(null, 2));
$this->assertEquals(new moodle_url(
- '/mod/quiz/attempt.php?attempt=123&page=1#'),
+ '/mod/quiz/attempt.php?attempt=123&page=1&cmid=0#'),
$attempt->attempt_url(3));
$this->assertEquals(new moodle_url(
- '/mod/quiz/attempt.php?attempt=123&page=1#q4'),
+ '/mod/quiz/attempt.php?attempt=123&page=1&cmid=0#q4'),
$attempt->attempt_url(4));
$this->assertEquals(new moodle_url(
// Summary page.
$this->assertEquals(new moodle_url(
- '/mod/quiz/summary.php?attempt=123'),
+ '/mod/quiz/summary.php?attempt=123&cmid=0'),
$attempt->summary_url());
// Review page.
$this->assertEquals(new moodle_url(
- '/mod/quiz/review.php?attempt=123'),
+ '/mod/quiz/review.php?attempt=123&cmid=0'),
$attempt->review_url());
$this->assertEquals(new moodle_url(
- '/mod/quiz/review.php?attempt=123&page=2'),
+ '/mod/quiz/review.php?attempt=123&page=2&cmid=0'),
$attempt->review_url(null, 2));
$this->assertEquals(new moodle_url(
- '/mod/quiz/review.php?attempt=123&page=1'),
+ '/mod/quiz/review.php?attempt=123&page=1&cmid=0'),
$attempt->review_url(3, -1, false));
$this->assertEquals(new moodle_url(
- '/mod/quiz/review.php?attempt=123&page=1#q4'),
+ '/mod/quiz/review.php?attempt=123&page=1&cmid=0#q4'),
$attempt->review_url(4, -1, false));
$this->assertEquals(new moodle_url(
- '/mod/quiz/review.php?attempt=123'),
+ '/mod/quiz/review.php?attempt=123&cmid=0'),
$attempt->review_url(null, 2, true));
$this->assertEquals(new moodle_url(
- '/mod/quiz/review.php?attempt=123'),
+ '/mod/quiz/review.php?attempt=123&cmid=0'),
$attempt->review_url(1, -1, true));
$this->assertEquals(new moodle_url(
- '/mod/quiz/review.php?attempt=123&page=2'),
+ '/mod/quiz/review.php?attempt=123&page=2&cmid=0'),
$attempt->review_url(null, 2, false));
$this->assertEquals(new moodle_url(
- '/mod/quiz/review.php?attempt=123&showall=0'),
+ '/mod/quiz/review.php?attempt=123&showall=0&cmid=0'),
$attempt->review_url(null, 0, false));
$this->assertEquals(new moodle_url(
- '/mod/quiz/review.php?attempt=123&showall=0'),
+ '/mod/quiz/review.php?attempt=123&showall=0&cmid=0'),
$attempt->review_url(1, -1, false));
$this->assertEquals(new moodle_url(
- '/mod/quiz/review.php?attempt=123&page=1'),
+ '/mod/quiz/review.php?attempt=123&page=1&cmid=0'),
$attempt->review_url(3, -1, false));
$this->assertEquals(new moodle_url(
- '/mod/quiz/review.php?attempt=123&page=2'),
+ '/mod/quiz/review.php?attempt=123&page=2&cmid=0'),
$attempt->review_url(null, 2));
$this->assertEquals(new moodle_url(
$attempt->review_url(1, -1, true, 0));
$this->assertEquals(new moodle_url(
- '/mod/quiz/review.php?attempt=123&page=2'),
+ '/mod/quiz/review.php?attempt=123&page=2&cmid=0'),
$attempt->review_url(null, 2, false, 0));
$this->assertEquals(new moodle_url(
$attempt->review_url(1, -1, false, 0));
$this->assertEquals(new moodle_url(
- '/mod/quiz/review.php?attempt=123&page=1#'),
+ '/mod/quiz/review.php?attempt=123&page=1&cmid=0#'),
$attempt->review_url(3, -1, false, 0));
// Review with more than 50 questions in the quiz.
'41,42,43,44,45,46,47,48,49,50,0,51,52,53,54,55,56,57,58,59,60,0');
$this->assertEquals(new moodle_url(
- '/mod/quiz/review.php?attempt=124'),
+ '/mod/quiz/review.php?attempt=124&cmid=0'),
$attempt->review_url());
$this->assertEquals(new moodle_url(
- '/mod/quiz/review.php?attempt=124&page=2'),
+ '/mod/quiz/review.php?attempt=124&page=2&cmid=0'),
$attempt->review_url(null, 2));
$this->assertEquals(new moodle_url(
- '/mod/quiz/review.php?attempt=124&page=1'),
+ '/mod/quiz/review.php?attempt=124&page=1&cmid=0'),
$attempt->review_url(11, -1, false));
$this->assertEquals(new moodle_url(
- '/mod/quiz/review.php?attempt=124&page=1#q12'),
+ '/mod/quiz/review.php?attempt=124&page=1&cmid=0#q12'),
$attempt->review_url(12, -1, false));
$this->assertEquals(new moodle_url(
- '/mod/quiz/review.php?attempt=124&showall=1'),
+ '/mod/quiz/review.php?attempt=124&showall=1&cmid=0'),
$attempt->review_url(null, 2, true));
$this->assertEquals(new moodle_url(
- '/mod/quiz/review.php?attempt=124&showall=1'),
+ '/mod/quiz/review.php?attempt=124&showall=1&cmid=0'),
$attempt->review_url(1, -1, true));
$this->assertEquals(new moodle_url(
- '/mod/quiz/review.php?attempt=124&page=2'),
+ '/mod/quiz/review.php?attempt=124&page=2&cmid=0'),
$attempt->review_url(null, 2, false));
$this->assertEquals(new moodle_url(
- '/mod/quiz/review.php?attempt=124'),
+ '/mod/quiz/review.php?attempt=124&cmid=0'),
$attempt->review_url(null, 0, false));
$this->assertEquals(new moodle_url(
- '/mod/quiz/review.php?attempt=124&page=1'),
+ '/mod/quiz/review.php?attempt=124&page=1&cmid=0'),
$attempt->review_url(11, -1, false));
$this->assertEquals(new moodle_url(
- '/mod/quiz/review.php?attempt=124&page=1#q12'),
+ '/mod/quiz/review.php?attempt=124&page=1&cmid=0#q12'),
$attempt->review_url(12, -1, false));
$this->assertEquals(new moodle_url(
- '/mod/quiz/review.php?attempt=124&page=2'),
+ '/mod/quiz/review.php?attempt=124&page=2&cmid=0'),
$attempt->review_url(null, 2));
$this->assertEquals(new moodle_url(
$attempt->review_url(1, -1, true, 0));
$this->assertEquals(new moodle_url(
- '/mod/quiz/review.php?attempt=124&page=2'),
+ '/mod/quiz/review.php?attempt=124&page=2&cmid=0'),
$attempt->review_url(null, 2, false, 0));
$this->assertEquals(new moodle_url(
$attempt->review_url(1, -1, false, 0));
$this->assertEquals(new moodle_url(
- '/mod/quiz/review.php?attempt=124&page=1#'),
+ '/mod/quiz/review.php?attempt=124&page=1&cmid=0#'),
$attempt->review_url(11, -1, false, 0));
}
}
groups_delete_group_members($course->id);
$this->assertEquals(1200, $DB->get_field('quiz_attempts', 'timecheckstate', array('id'=>$attemptid)));
}
+
+ /**
+ * Test the functions quiz_create_attempt_handling_errors
+ */
+ public function test_quiz_create_attempt_handling_errors() {
+ $this->resetAfterTest(true);
+ $this->setAdminUser();
+
+ // Make a quiz.
+ $course = $this->getDataGenerator()->create_course();
+ $user1 = $this->getDataGenerator()->create_user();
+ $student = $this->getDataGenerator()->create_user();
+ $this->getDataGenerator()->enrol_user($student->id, $course->id, 'student');
+ $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz');
+ $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
+ $quiz = $quizgenerator->create_instance(array('course' => $course->id, 'questionsperpage' => 0, 'grade' => 100.0,
+ 'sumgrades' => 2));
+ // Create questions.
+ $cat = $questiongenerator->create_question_category();
+ $saq = $questiongenerator->create_question('shortanswer', null, array('category' => $cat->id));
+ $numq = $questiongenerator->create_question('numerical', null, array('category' => $cat->id));
+ // Add them to the quiz.
+ quiz_add_quiz_question($saq->id, $quiz);
+ quiz_add_quiz_question($numq->id, $quiz);
+ $quizobj = quiz::create($quiz->id, $user1->id);
+ $quba = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context());
+ $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour);
+ $timenow = time();
+ // Create an attempt.
+ $attempt = quiz_create_attempt($quizobj, 1, false, $timenow, false, $user1->id);
+ quiz_start_new_attempt($quizobj, $quba, $attempt, 1, $timenow);
+ quiz_attempt_save_started($quizobj, $quba, $attempt);
+ $result = quiz_create_attempt_handling_errors($attempt->id, $quiz->cmid);
+ $this->assertEquals($result->get_attemptid(), $attempt->id);
+ try {
+ $result = quiz_create_attempt_handling_errors($attempt->id, 9999);
+ $this->fail('Exception expected due to invalid course module id.');
+ } catch (moodle_exception $e) {
+ $this->assertEquals('invalidcoursemodule', $e->errorcode);
+ }
+ try {
+ quiz_create_attempt_handling_errors(9999, $result->get_cmid());
+ $this->fail('Exception expected due to quiz content change.');
+ } catch (moodle_exception $e) {
+ $this->assertEquals('attempterrorcontentchange', $e->errorcode);
+ }
+ try {
+ quiz_create_attempt_handling_errors(9999);
+ $this->fail('Exception expected due to invalid quiz attempt id.');
+ } catch (moodle_exception $e) {
+ $this->assertEquals('attempterrorinvalid', $e->errorcode);
+ }
+ // Set up as normal user without permission to view preview.
+ $this->setUser($student->id);
+ try {
+ quiz_create_attempt_handling_errors(9999, $result->get_cmid());
+ $this->fail('Exception expected due to quiz content change for user without permission.');
+ } catch (moodle_exception $e) {
+ $this->assertEquals('attempterrorcontentchangeforuser', $e->errorcode);
+ }
+ try {
+ quiz_create_attempt_handling_errors($attempt->id, 9999);
+ $this->fail('Exception expected due to invalid course module id for user without permission.');
+ } catch (moodle_exception $e) {
+ $this->assertEquals('invalidcoursemodule', $e->errorcode);
+ }
+ }
}