public function test_quiz_report_overview_report_forcesubmit_specific_attempt() { global $DB; $this->resetAfterTest(); $generator = $this->getDataGenerator(); $quizgenerator = $generator->get_plugin_generator('mod_quiz'); $questiongenerator = $generator->get_plugin_generator('core_question'); // Make a user to do the quiz. $user1 = $generator->create_user(); $user2 = $generator->create_user(); $user3 = $generator->create_user(); // Create our course. $course = $generator->create_course(array('visible' => true)); // Create the quiz. $quiz = $quizgenerator->create_instance(array('course' => $course->id, 'visible' => true, 'questionsperpage' => 0, 'grade' => 100.0, 'sumgrades' => 2)); // Create two 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 the questions to the quiz. quiz_add_quiz_question($saq->id, $quiz); quiz_add_quiz_question($numq->id, $quiz); // Get a quiz object with user access overrides. $quizobj = quiz::create($quiz->id, $user1->id); $quizobj2 = quiz::create($quiz->id, $user2->id); $quizobj3 = quiz::create($quiz->id, $user3->id); // Start the attempt. $quba = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context()); $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour); $quba2 = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj2->get_context()); $quba2->set_preferred_behaviour($quizobj2->get_quiz()->preferredbehaviour); $quba3 = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj3->get_context()); $quba3->set_preferred_behaviour($quizobj3->get_quiz()->preferredbehaviour); // Create a quiz attempt. $timenow = time(); $attempt = quiz_create_attempt($quizobj, 1, false, $timenow, false, $user1->id); $attempt2 = quiz_create_attempt($quizobj2, 1, false, $timenow, false, $user2->id); $attempt3 = quiz_create_attempt($quizobj3, 1, false, $timenow, false, $user3->id); // Start the attempt. quiz_start_new_attempt($quizobj, $quba, $attempt, 1, $timenow); quiz_attempt_save_started($quizobj, $quba, $attempt); quiz_start_new_attempt($quizobj2, $quba2, $attempt2, 1, $timenow); quiz_attempt_save_started($quizobj2, $quba2, $attempt2); quiz_start_new_attempt($quizobj3, $quba3, $attempt3, 1, $timenow); quiz_attempt_save_started($quizobj3, $quba3, $attempt3); // Answer first question and set it overdue. $tosubmit = array(1 => array('answer' => 'frog')); $tosubmit2 = array(1 => array('answer' => 'tiger')); $tosubmit3 = array(1 => array('answer' => 'tiger')); $attemptobj = quiz_attempt::create($attempt->id); $attemptobj->process_submitted_actions($timenow, true, $tosubmit); $attemptobj2 = quiz_attempt::create($attempt2->id); $attemptobj2->process_submitted_actions($timenow, true, $tosubmit2); $attemptobj3 = quiz_attempt::create($attempt3->id); $attemptobj3->process_submitted_actions($timenow, true, $tosubmit3); // Finish the attempt. $attemptobj = quiz_attempt::create($attempt->id); $this->assertTrue($attemptobj->has_response_to_at_least_one_graded_question()); $attemptobj->process_abandon($timenow, false); // Re-load quiz attempt2 data. $attemptobj = quiz_attempt::create($attempt->id); $attemptobj2 = quiz_attempt::create($attempt2->id); $attemptobj3 = quiz_attempt::create($attempt3->id); // Check that the state of the attempt is as expected. $this->assertEquals(1, $attemptobj->get_attempt_number()); $this->assertEquals(quiz_attempt::ABANDONED, $attemptobj->get_state()); $this->assertEquals($user1->id, $attemptobj->get_userid()); $this->assertTrue($attemptobj->has_response_to_at_least_one_graded_question()); // Check that the state of the attempt2 is as expected. $this->assertEquals(1, $attemptobj2->get_attempt_number()); $this->assertEquals(quiz_attempt::OVERDUE, $attemptobj2->get_state()); $this->assertEquals($user2->id, $attemptobj2->get_userid()); $this->assertTrue($attemptobj2->has_response_to_at_least_one_graded_question()); // Check that the state of the attempt3 is as expected. $this->assertEquals(1, $attemptobj3->get_attempt_number()); $this->assertEquals(quiz_attempt::OVERDUE, $attemptobj3->get_state()); $this->assertEquals($user3->id, $attemptobj3->get_userid()); $this->assertTrue($attemptobj3->has_response_to_at_least_one_graded_question()); // Force submit the attempts. $overviewreport = new quiz_overview_report_testable(); $overviewreport->forcesubmit_attempts($quiz, false, array(), array($attempt->id, $attempt3->id)); // Check that it is now finished. $attemptobj = quiz_attempt::create($attempt->id); $this->assertEquals(quiz_attempt::FINISHED, $attemptobj->get_state()); $attemptobj2 = quiz_attempt::create($attempt2->id); $this->assertEquals(quiz_attempt::OVERDUE, $attemptobj2->get_state()); $attemptobj3 = quiz_attempt::create($attempt3->id); $this->assertEquals(quiz_attempt::FINISHED, $attemptobj3->get_state()); }
private static function quiz_attempt_finish($timenow, $attemptid, $toolate, $uid, $request, $key) { global $USER; $attemptobj = ''; $USER->id = $uid; $attemptobj = quiz_attempt::create($attemptid); $postarray = array("attempt" => "{$attemptid}", "finishattempt" => "1", "timeup" => "0", "slots" => "", "sesskey" => "{$USER->sesskey}"); $attemptobj->process_finish($timenow, !$toolate, $postarray); $output = self::get_completed_response($request, $attemptid, $key); }
protected function assert_response_test($quizattemptid, $responses) { $quizattempt = quiz_attempt::create($quizattemptid); foreach ($responses['slot'] as $slot => $tests) { $slothastests = false; foreach ($tests as $test) { if ('' !== $test) { $slothastests = true; } } if (!$slothastests) { continue; } $qa = $quizattempt->get_question_attempt($slot); $stepswithsubmit = $qa->get_steps_with_submitted_response_iterator(); $step = $stepswithsubmit[$responses['submittedstepno']]; if (null === $step) { throw new coding_exception("There is no step no {$responses['submittedstepno']} " . "for slot {$slot} in quizattempt {$responses['quizattempt']}!"); } foreach (array('responsesummary', 'fraction', 'state') as $column) { if (isset($tests[$column]) && $tests[$column] != '') { switch ($column) { case 'responsesummary': $actual = $qa->get_question()->summarise_response($step->get_qt_data()); break; case 'fraction': if (count($stepswithsubmit) == $responses['submittedstepno']) { // If this is the last step then we need to look at the fraction after the question has been // finished. $actual = $qa->get_fraction(); } else { $actual = $step->get_fraction(); } break; case 'state': if (count($stepswithsubmit) == $responses['submittedstepno']) { // If this is the last step then we need to look at the state after the question has been // finished. $state = $qa->get_state(); } else { $state = $step->get_state(); } $actual = substr(get_class($state), strlen('question_state_')); } $expected = $tests[$column]; $failuremessage = "Error in quizattempt {$responses['quizattempt']} in {$column}, slot {$slot}, " . "submittedstepno {$responses['submittedstepno']}"; $this->assertEquals($expected, $actual, $failuremessage); } } } }
/** * Stops the attempt and saves the grade. */ public function end_quiz_attmept($attempt) { $timenow = time(); $attemptobj = quiz_attempt::create($attempt->id); $attemptobj->process_finish($timenow, true); }
/** * Test checking the completion state of a quiz. */ public function test_quiz_get_completion_state() { global $CFG, $DB; $this->resetAfterTest(true); // Enable completion before creating modules, otherwise the completion data is not written in DB. $CFG->enablecompletion = true; // Create a course and student. $course = $this->getDataGenerator()->create_course(array('enablecompletion' => true)); $passstudent = $this->getDataGenerator()->create_user(); $failstudent = $this->getDataGenerator()->create_user(); $studentrole = $DB->get_record('role', array('shortname' => 'student')); $this->assertNotEmpty($studentrole); // Enrol students. $this->assertTrue($this->getDataGenerator()->enrol_user($passstudent->id, $course->id, $studentrole->id)); $this->assertTrue($this->getDataGenerator()->enrol_user($failstudent->id, $course->id, $studentrole->id)); // Make a scale and an outcome. $scale = $this->getDataGenerator()->create_scale(); $data = array('courseid' => $course->id, 'fullname' => 'Team work', 'shortname' => 'Team work', 'scaleid' => $scale->id); $outcome = $this->getDataGenerator()->create_grade_outcome($data); // Make a quiz with the outcome on. $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz'); $data = array('course' => $course->id, 'outcome_' . $outcome->id => 1, 'grade' => 100.0, 'questionsperpage' => 0, 'sumgrades' => 1, 'completion' => COMPLETION_TRACKING_AUTOMATIC, 'completionpass' => 1); $quiz = $quizgenerator->create_instance($data); $cm = get_coursemodule_from_id('quiz', $quiz->cmid); // Create a couple of questions. $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question'); $cat = $questiongenerator->create_question_category(); $question = $questiongenerator->create_question('numerical', null, array('category' => $cat->id)); quiz_add_quiz_question($question->id, $quiz); $quizobj = quiz::create($quiz->id, $passstudent->id); // Set grade to pass. $item = grade_item::fetch(array('courseid' => $course->id, 'itemtype' => 'mod', 'itemmodule' => 'quiz', 'iteminstance' => $quiz->id, 'outcomeid' => null)); $item->gradepass = 80; $item->update(); // Start the passing attempt. $quba = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context()); $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour); $timenow = time(); $attempt = quiz_create_attempt($quizobj, 1, false, $timenow, false, $passstudent->id); quiz_start_new_attempt($quizobj, $quba, $attempt, 1, $timenow); quiz_attempt_save_started($quizobj, $quba, $attempt); // Process some responses from the student. $attemptobj = quiz_attempt::create($attempt->id); $tosubmit = array(1 => array('answer' => '3.14')); $attemptobj->process_submitted_actions($timenow, false, $tosubmit); // Finish the attempt. $attemptobj = quiz_attempt::create($attempt->id); $this->assertTrue($attemptobj->has_response_to_at_least_one_graded_question()); $attemptobj->process_finish($timenow, false); // Start the failing attempt. $quba = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context()); $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour); $timenow = time(); $attempt = quiz_create_attempt($quizobj, 1, false, $timenow, false, $failstudent->id); quiz_start_new_attempt($quizobj, $quba, $attempt, 1, $timenow); quiz_attempt_save_started($quizobj, $quba, $attempt); // Process some responses from the student. $attemptobj = quiz_attempt::create($attempt->id); $tosubmit = array(1 => array('answer' => '0')); $attemptobj->process_submitted_actions($timenow, false, $tosubmit); // Finish the attempt. $attemptobj = quiz_attempt::create($attempt->id); $this->assertTrue($attemptobj->has_response_to_at_least_one_graded_question()); $attemptobj->process_finish($timenow, false); // Check the results. $this->assertTrue(quiz_get_completion_state($course, $cm, $passstudent->id, 'return')); $this->assertFalse(quiz_get_completion_state($course, $cm, $failstudent->id, 'return')); }
public function test_attempt_started() { global $USER; list($quizobj, $quba, $attempt) = $this->prepare_quiz_data(); $attemptobj = quiz_attempt::create($attempt->id); // Catch the event. $sink = $this->redirectEvents(); quiz_fire_attempt_started_event($attempt, $quizobj); $events = $sink->get_events(); $sink->close(); // Legacy event data. $legacydata = new stdClass(); $legacydata->component = 'mod_quiz'; $legacydata->attemptid = $attempt->id; $legacydata->timestart = $attempt->timestart; $legacydata->timestamp = $attempt->timestart; $legacydata->userid = $attempt->userid; $legacydata->quizid = $quizobj->get_quizid(); $legacydata->cmid = $quizobj->get_cmid(); $legacydata->courseid = $quizobj->get_courseid(); // Validate the event. $this->assertCount(1, $events); $event = $events[0]; $this->assertInstanceOf('\\mod_quiz\\event\\attempt_started', $event); $this->assertEquals('quiz_attempts', $event->objecttable); $this->assertEquals($attempt->id, $event->objectid); $this->assertEquals($attempt->userid, $event->relateduserid); $this->assertEquals($quizobj->get_context(), $event->get_context()); $this->assertEquals('quiz_attempt_started', $event->get_legacy_eventname()); $this->assertEventLegacyData($legacydata, $event); }
public function test_quiz_get_user_attempts() { global $DB; $this->resetAfterTest(); $dg = $this->getDataGenerator(); $quizgen = $dg->get_plugin_generator('mod_quiz'); $course = $dg->create_course(); $u1 = $dg->create_user(); $u2 = $dg->create_user(); $u3 = $dg->create_user(); $u4 = $dg->create_user(); $role = $DB->get_record('role', ['shortname' => 'student']); $dg->enrol_user($u1->id, $course->id, $role->id); $dg->enrol_user($u2->id, $course->id, $role->id); $dg->enrol_user($u3->id, $course->id, $role->id); $dg->enrol_user($u4->id, $course->id, $role->id); $quiz1 = $quizgen->create_instance(['course' => $course->id, 'sumgrades' => 2]); $quiz2 = $quizgen->create_instance(['course' => $course->id, 'sumgrades' => 2]); // Questions. $questgen = $dg->get_plugin_generator('core_question'); $quizcat = $questgen->create_question_category(); $question = $questgen->create_question('numerical', null, ['category' => $quizcat->id]); quiz_add_quiz_question($question->id, $quiz1); quiz_add_quiz_question($question->id, $quiz2); $quizobj1a = quiz::create($quiz1->id, $u1->id); $quizobj1b = quiz::create($quiz1->id, $u2->id); $quizobj1c = quiz::create($quiz1->id, $u3->id); $quizobj1d = quiz::create($quiz1->id, $u4->id); $quizobj2a = quiz::create($quiz2->id, $u1->id); // Set attempts. $quba1a = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj1a->get_context()); $quba1a->set_preferred_behaviour($quizobj1a->get_quiz()->preferredbehaviour); $quba1b = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj1b->get_context()); $quba1b->set_preferred_behaviour($quizobj1b->get_quiz()->preferredbehaviour); $quba1c = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj1c->get_context()); $quba1c->set_preferred_behaviour($quizobj1c->get_quiz()->preferredbehaviour); $quba1d = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj1d->get_context()); $quba1d->set_preferred_behaviour($quizobj1d->get_quiz()->preferredbehaviour); $quba2a = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj2a->get_context()); $quba2a->set_preferred_behaviour($quizobj2a->get_quiz()->preferredbehaviour); $timenow = time(); // User 1 passes quiz 1. $attempt = quiz_create_attempt($quizobj1a, 1, false, $timenow, false, $u1->id); quiz_start_new_attempt($quizobj1a, $quba1a, $attempt, 1, $timenow); quiz_attempt_save_started($quizobj1a, $quba1a, $attempt); $attemptobj = quiz_attempt::create($attempt->id); $attemptobj->process_submitted_actions($timenow, false, [1 => ['answer' => '3.14']]); $attemptobj->process_finish($timenow, false); // User 2 goes overdue in quiz 1. $attempt = quiz_create_attempt($quizobj1b, 1, false, $timenow, false, $u2->id); quiz_start_new_attempt($quizobj1b, $quba1b, $attempt, 1, $timenow); quiz_attempt_save_started($quizobj1b, $quba1b, $attempt); $attemptobj = quiz_attempt::create($attempt->id); $attemptobj->process_going_overdue($timenow, true); // User 3 does not finish quiz 1. $attempt = quiz_create_attempt($quizobj1c, 1, false, $timenow, false, $u3->id); quiz_start_new_attempt($quizobj1c, $quba1c, $attempt, 1, $timenow); quiz_attempt_save_started($quizobj1c, $quba1c, $attempt); // User 4 abandons the quiz 1. $attempt = quiz_create_attempt($quizobj1d, 1, false, $timenow, false, $u4->id); quiz_start_new_attempt($quizobj1d, $quba1d, $attempt, 1, $timenow); quiz_attempt_save_started($quizobj1d, $quba1d, $attempt); $attemptobj = quiz_attempt::create($attempt->id); $attemptobj->process_abandon($timenow, true); // User 1 attempts the quiz three times (abandon, finish, in progress). $quba2a = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj2a->get_context()); $quba2a->set_preferred_behaviour($quizobj2a->get_quiz()->preferredbehaviour); $attempt = quiz_create_attempt($quizobj2a, 1, false, $timenow, false, $u1->id); quiz_start_new_attempt($quizobj2a, $quba2a, $attempt, 1, $timenow); quiz_attempt_save_started($quizobj2a, $quba2a, $attempt); $attemptobj = quiz_attempt::create($attempt->id); $attemptobj->process_abandon($timenow, true); $quba2a = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj2a->get_context()); $quba2a->set_preferred_behaviour($quizobj2a->get_quiz()->preferredbehaviour); $attempt = quiz_create_attempt($quizobj2a, 2, false, $timenow, false, $u1->id); quiz_start_new_attempt($quizobj2a, $quba2a, $attempt, 2, $timenow); quiz_attempt_save_started($quizobj2a, $quba2a, $attempt); $attemptobj = quiz_attempt::create($attempt->id); $attemptobj->process_finish($timenow, false); $quba2a = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj2a->get_context()); $quba2a->set_preferred_behaviour($quizobj2a->get_quiz()->preferredbehaviour); $attempt = quiz_create_attempt($quizobj2a, 3, false, $timenow, false, $u1->id); quiz_start_new_attempt($quizobj2a, $quba2a, $attempt, 3, $timenow); quiz_attempt_save_started($quizobj2a, $quba2a, $attempt); // Check for user 1. $attempts = quiz_get_user_attempts($quiz1->id, $u1->id, 'all'); $this->assertCount(1, $attempts); $attempt = array_shift($attempts); $this->assertEquals(quiz_attempt::FINISHED, $attempt->state); $this->assertEquals($u1->id, $attempt->userid); $this->assertEquals($quiz1->id, $attempt->quiz); $attempts = quiz_get_user_attempts($quiz1->id, $u1->id, 'finished'); $this->assertCount(1, $attempts); $attempt = array_shift($attempts); $this->assertEquals(quiz_attempt::FINISHED, $attempt->state); $this->assertEquals($u1->id, $attempt->userid); $this->assertEquals($quiz1->id, $attempt->quiz); $attempts = quiz_get_user_attempts($quiz1->id, $u1->id, 'unfinished'); $this->assertCount(0, $attempts); // Check for user 2. $attempts = quiz_get_user_attempts($quiz1->id, $u2->id, 'all'); $this->assertCount(1, $attempts); $attempt = array_shift($attempts); $this->assertEquals(quiz_attempt::OVERDUE, $attempt->state); $this->assertEquals($u2->id, $attempt->userid); $this->assertEquals($quiz1->id, $attempt->quiz); $attempts = quiz_get_user_attempts($quiz1->id, $u2->id, 'finished'); $this->assertCount(0, $attempts); $attempts = quiz_get_user_attempts($quiz1->id, $u2->id, 'unfinished'); $this->assertCount(1, $attempts); $attempt = array_shift($attempts); $this->assertEquals(quiz_attempt::OVERDUE, $attempt->state); $this->assertEquals($u2->id, $attempt->userid); $this->assertEquals($quiz1->id, $attempt->quiz); // Check for user 3. $attempts = quiz_get_user_attempts($quiz1->id, $u3->id, 'all'); $this->assertCount(1, $attempts); $attempt = array_shift($attempts); $this->assertEquals(quiz_attempt::IN_PROGRESS, $attempt->state); $this->assertEquals($u3->id, $attempt->userid); $this->assertEquals($quiz1->id, $attempt->quiz); $attempts = quiz_get_user_attempts($quiz1->id, $u3->id, 'finished'); $this->assertCount(0, $attempts); $attempts = quiz_get_user_attempts($quiz1->id, $u3->id, 'unfinished'); $this->assertCount(1, $attempts); $attempt = array_shift($attempts); $this->assertEquals(quiz_attempt::IN_PROGRESS, $attempt->state); $this->assertEquals($u3->id, $attempt->userid); $this->assertEquals($quiz1->id, $attempt->quiz); // Check for user 4. $attempts = quiz_get_user_attempts($quiz1->id, $u4->id, 'all'); $this->assertCount(1, $attempts); $attempt = array_shift($attempts); $this->assertEquals(quiz_attempt::ABANDONED, $attempt->state); $this->assertEquals($u4->id, $attempt->userid); $this->assertEquals($quiz1->id, $attempt->quiz); $attempts = quiz_get_user_attempts($quiz1->id, $u4->id, 'finished'); $this->assertCount(1, $attempts); $attempt = array_shift($attempts); $this->assertEquals(quiz_attempt::ABANDONED, $attempt->state); $this->assertEquals($u4->id, $attempt->userid); $this->assertEquals($quiz1->id, $attempt->quiz); $attempts = quiz_get_user_attempts($quiz1->id, $u4->id, 'unfinished'); $this->assertCount(0, $attempts); // Multiple attempts for user 1 in quiz 2. $attempts = quiz_get_user_attempts($quiz2->id, $u1->id, 'all'); $this->assertCount(3, $attempts); $attempt = array_shift($attempts); $this->assertEquals(quiz_attempt::ABANDONED, $attempt->state); $this->assertEquals($u1->id, $attempt->userid); $this->assertEquals($quiz2->id, $attempt->quiz); $attempt = array_shift($attempts); $this->assertEquals(quiz_attempt::FINISHED, $attempt->state); $this->assertEquals($u1->id, $attempt->userid); $this->assertEquals($quiz2->id, $attempt->quiz); $attempt = array_shift($attempts); $this->assertEquals(quiz_attempt::IN_PROGRESS, $attempt->state); $this->assertEquals($u1->id, $attempt->userid); $this->assertEquals($quiz2->id, $attempt->quiz); $attempts = quiz_get_user_attempts($quiz2->id, $u1->id, 'finished'); $this->assertCount(2, $attempts); $attempt = array_shift($attempts); $this->assertEquals(quiz_attempt::ABANDONED, $attempt->state); $attempt = array_shift($attempts); $this->assertEquals(quiz_attempt::FINISHED, $attempt->state); $attempts = quiz_get_user_attempts($quiz2->id, $u1->id, 'unfinished'); $this->assertCount(1, $attempts); $attempt = array_shift($attempts); // Multiple quiz attempts fetched at once. $attempts = quiz_get_user_attempts([$quiz1->id, $quiz2->id], $u1->id, 'all'); $this->assertCount(4, $attempts); $attempt = array_shift($attempts); $this->assertEquals(quiz_attempt::FINISHED, $attempt->state); $this->assertEquals($u1->id, $attempt->userid); $this->assertEquals($quiz1->id, $attempt->quiz); $attempt = array_shift($attempts); $this->assertEquals(quiz_attempt::ABANDONED, $attempt->state); $this->assertEquals($u1->id, $attempt->userid); $this->assertEquals($quiz2->id, $attempt->quiz); $attempt = array_shift($attempts); $this->assertEquals(quiz_attempt::FINISHED, $attempt->state); $this->assertEquals($u1->id, $attempt->userid); $this->assertEquals($quiz2->id, $attempt->quiz); $attempt = array_shift($attempts); $this->assertEquals(quiz_attempt::IN_PROGRESS, $attempt->state); $this->assertEquals($u1->id, $attempt->userid); $this->assertEquals($quiz2->id, $attempt->quiz); }
/** * Test get_attempt_access_information */ public function test_get_attempt_access_information() { global $DB; // Create a new quiz with attempts. $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz'); $data = array('course' => $this->course->id, 'sumgrades' => 2); $quiz = $quizgenerator->create_instance($data); // Create some questions. $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question'); $cat = $questiongenerator->create_question_category(); $question = $questiongenerator->create_question('numerical', null, array('category' => $cat->id)); quiz_add_quiz_question($question->id, $quiz); $question = $questiongenerator->create_question('shortanswer', null, array('category' => $cat->id)); quiz_add_quiz_question($question->id, $quiz); // Add new question types in the category (for the random one). $question = $questiongenerator->create_question('truefalse', null, array('category' => $cat->id)); $question = $questiongenerator->create_question('essay', null, array('category' => $cat->id)); $question = $questiongenerator->create_question('random', null, array('category' => $cat->id)); quiz_add_quiz_question($question->id, $quiz); $quizobj = quiz::create($quiz->id, $this->student->id); // Set grade to pass. $item = grade_item::fetch(array('courseid' => $this->course->id, 'itemtype' => 'mod', 'itemmodule' => 'quiz', 'iteminstance' => $quiz->id, 'outcomeid' => null)); $item->gradepass = 80; $item->update(); $this->setUser($this->student); // Default restrictions (none). $result = mod_quiz_external::get_attempt_access_information($quiz->id); $result = external_api::clean_returnvalue(mod_quiz_external::get_attempt_access_information_returns(), $result); $expected = array('isfinished' => false, 'preventnewattemptreasons' => [], 'warnings' => []); $this->assertEquals($expected, $result); // Limited attempts. $quiz->attempts = 1; $DB->update_record('quiz', $quiz); // Now, do one attempt. $quba = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context()); $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour); $timenow = time(); $attempt = quiz_create_attempt($quizobj, 1, false, $timenow, false, $this->student->id); quiz_start_new_attempt($quizobj, $quba, $attempt, 1, $timenow); quiz_attempt_save_started($quizobj, $quba, $attempt); // Process some responses from the student. $attemptobj = quiz_attempt::create($attempt->id); $tosubmit = array(1 => array('answer' => '3.14')); $attemptobj->process_submitted_actions($timenow, false, $tosubmit); // Finish the attempt. $attemptobj = quiz_attempt::create($attempt->id); $this->assertTrue($attemptobj->has_response_to_at_least_one_graded_question()); $attemptobj->process_finish($timenow, false); // Can we start a new attempt? We shall not! $result = mod_quiz_external::get_attempt_access_information($quiz->id, $attempt->id); $result = external_api::clean_returnvalue(mod_quiz_external::get_attempt_access_information_returns(), $result); // Now new attemps allowed. $this->assertCount(1, $result['preventnewattemptreasons']); $this->assertFalse($result['ispreflightcheckrequired']); $this->assertEquals(get_string('nomoreattempts', 'quiz'), $result['preventnewattemptreasons'][0]); }
/** * This method changes to the desired user and attempts to review * the quiz. The message is returned to the caller. * * @param object $user The user object for the person attempting to review * @param int $attemptid The ID of the attempt to review * @return mixed {false|message indicating reason} * */ private function check_ipaddress_review($user, $attemptid) { $this->setUser($user); // Create new attempt object from ID to reload from database. $attemptobj = quiz_attempt::create($attemptid); $accessmanager = $attemptobj->get_access_manager(time()); return $accessmanager->prevent_review_ipaddress(); }
/** * Called via pluginfile.php -> question_pluginfile to serve files belonging to * a question in a question_attempt when that attempt is a quiz attempt. * * @param object $course course settings object * @param object $context context object * @param string $component the name of the component we are serving files for. * @param string $filearea the name of the file area. * @param array $args the remaining bits of the file path. * @param bool $forcedownload whether the user must be forced to download the file. * @return bool false if file not found, does not return if found - justsend the file */ function quiz_question_pluginfile($course, $context, $component, $filearea, $attemptid, $questionid, $args, $forcedownload) { global $USER, $CFG; require_once($CFG->dirroot . '/mod/quiz/locallib.php'); $attemptobj = quiz_attempt::create($attemptid); require_login($attemptobj->get_courseid(), false, $attemptobj->get_cm()); $questionids = array($questionid); $attemptobj->load_questions($questionids); $attemptobj->load_question_states($questionids); if ($attemptobj->is_own_attempt() && !$attemptobj->is_finished()) { // In the middle of an attempt. if (!$attemptobj->is_preview_user()) { $attemptobj->require_capability('mod/quiz:attempt'); } $isreviewing = false; } else { // Reviewing an attempt. $attemptobj->check_review_capability(); $isreviewing = true; } if (!$attemptobj->check_file_access($questionid, $isreviewing, $context->id, $component, $filearea, $args, $forcedownload)) { send_file_not_found(); } $fs = get_file_storage(); $relativepath = implode('/', $args); $fullpath = "/$context->id/$component/$filearea/$relativepath"; if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) { send_file_not_found(); } send_stored_file($file, 0, 0, $forcedownload); }
$PAGE->set_heading(format_string($course->fullname)); $PAGE->set_context($context); $PAGE->set_cacheable(false); $PAGE->requires->css("/mod/studyplan/view.css"); $PAGE->add_body_class('studyplan-view'); echo $OUTPUT->header(); // Output starts here echo $OUTPUT->heading($studyplan->name); if ($studyplan->intro) { // Conditions to show the intro can change to look for own settings or whatever echo $OUTPUT->box(format_module_intro('studyplan', $studyplan, $cm->id), 'studyplan-intro', 'studyplanintro'); } if ($studyplan->standardblock) { echo '<div class="studyplan-standard">'; include dirname(__FILE__) . '/intro.php'; echo '</div>'; } $attempts = quiz_get_user_attempts($studyplan->quiz, $USER->id, 'finished', true); if (empty($attempts)) { $url = new moodle_url('/mod/quiz/view.php', array('q' => $studyplan->quiz)); $quiz_name = htmlentities(sp_get_quiz_name($studyplan->quiz)); print "<h2 class=\"studyplan-header studyplan-no-quiz\">" . get_string('youhavenotfinished', 'studyplan') . " <a href=\"{$url}\">{$quiz_name}</a>." . "</h2>"; } else { $lastfinishedattempt = end($attempts); $attemptobj = quiz_attempt::create($lastfinishedattempt->id); $questionids = sp_get_questionids_from_attempt($attemptobj); $presummary = sp_presummarize($attemptobj, $questionids, $showtabulation); echo sp_render_block($studyplan->id, $presummary, false, false, $showtabulation, "student"); } // Finish the page echo $OUTPUT->footer();
/** * @param $results PHPUnit_Extensions_Database_DataSet_ITable the results data from the csv file. * @param $attemptids array attempt no as in csv file => the id of the quiz_attempt as stored in the db. */ protected function check_attempts_results($results, $attemptids) { for ($rowno = 0; $rowno < $results->getRowCount(); $rowno++) { $result = $this->explode_dot_separated_keys_to_make_subindexs($results->getRow($rowno)); // Re-load quiz attempt data. $attemptobj = quiz_attempt::create($attemptids[$result['quizattempt']]); $this->check_attempt_results($result, $attemptobj); } }
function sp_calculate_student_progress($studyplanid = null, $userid = null, $store = true, $gettext = true) { global $USER, $STUDENT, $DB; global $STUDENT_PROGRESS; if ($studyplanid === null) { return; } if ($userid === null) { return; } if ($userid != $STUDENT->id) { $STUDENT = $DB->get_record('user', array('id' => $userid), '*', MUST_EXIST); } $STUDENT_PROGRESS = array(); $studyplan = $DB->get_record('studyplan', array('id' => $studyplanid), '*', MUST_EXIST); $attempts = quiz_get_user_attempts($studyplan->quiz, $userid, 'finished', true); if (!empty($attempts)) { $lastfinishedattempt = end($attempts); $attemptobj = quiz_attempt::create($lastfinishedattempt->id); $questionids = sp_get_questionids_from_attempt($attemptobj); $presummary = sp_presummarize($attemptobj, $questionids); #calculate percent by rendering the block sp_render_block($studyplan->id, $presummary, false, true); } if ($store) { sp_store_student_progress($studyplanid, $userid); } if (!$gettext) { return; } return sp_student_progress_as_percentage_text(); }
} $responses = openssl_decrypt($data->responses, 'AES-256-CBC', $aeskey, 0, $iv); if (!$responses) { throw new coding_exception('Could not decrypt the responses. ' . openssl_error_string()); } } else { $responses = $data->responses; } $postdata = array(); parse_str($responses, $postdata); if (!isset($postdata['attempt'])) { throw new coding_exception('The uploaded data did not include an attempt id.'); } echo html_writer::tag('textarea', s(print_r($postdata, true)), array('readonly' => 'readonly')); // Load the attempt. $attemptobj = quiz_attempt::create($postdata['attempt']); if ($attemptobj->get_cmid() != $cmid) { throw new coding_exception('The uploaded data does not belong to this quiz.'); } // Process the uploaded data. (We have to do weird fakery with $_POST && $_REQUEST.) $timenow = time(); $postdata['sesskey'] = sesskey(); $originalpost = $_POST; $_POST = $postdata; $originalrequest = $_REQUEST; $_REQUEST = $postdata; if ($fromform->finishattempts) { $attemptobj->process_finish($timenow, true); } else { $attemptobj->process_submitted_actions($timenow); }
/** * Test start_attempt */ public function test_start_attempt() { global $DB; // Create a new quiz with attempts. $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz'); $data = array('course' => $this->course->id, 'sumgrades' => 1); $quiz = $quizgenerator->create_instance($data); $context = context_module::instance($quiz->cmid); try { mod_quiz_external::start_attempt($quiz->id); $this->fail('Exception expected due to missing questions.'); } catch (moodle_quiz_exception $e) { $this->assertEquals('noquestionsfound', $e->errorcode); } // Create a question. $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question'); $cat = $questiongenerator->create_question_category(); $question = $questiongenerator->create_question('numerical', null, array('category' => $cat->id)); quiz_add_quiz_question($question->id, $quiz); $quizobj = quiz::create($quiz->id, $this->student->id); // Set grade to pass. $item = grade_item::fetch(array('courseid' => $this->course->id, 'itemtype' => 'mod', 'itemmodule' => 'quiz', 'iteminstance' => $quiz->id, 'outcomeid' => null)); $item->gradepass = 80; $item->update(); $this->setUser($this->student); // Try to open attempt in closed quiz. $quiz->timeopen = time() - WEEKSECS; $quiz->timeclose = time() - DAYSECS; $DB->update_record('quiz', $quiz); $result = mod_quiz_external::start_attempt($quiz->id); $result = external_api::clean_returnvalue(mod_quiz_external::start_attempt_returns(), $result); $this->assertEquals([], $result['attempt']); $this->assertCount(1, $result['warnings']); // Now with a password. $quiz->timeopen = 0; $quiz->timeclose = 0; $quiz->password = '******'; $DB->update_record('quiz', $quiz); try { mod_quiz_external::start_attempt($quiz->id, array(array("name" => "quizpassword", "value" => 'bad'))); $this->fail('Exception expected due to invalid passwod.'); } catch (moodle_exception $e) { $this->assertEquals(get_string('passworderror', 'quizaccess_password'), $e->errorcode); } // Now, try everything correct. $result = mod_quiz_external::start_attempt($quiz->id, array(array("name" => "quizpassword", "value" => 'abc'))); $result = external_api::clean_returnvalue(mod_quiz_external::start_attempt_returns(), $result); $this->assertEquals(1, $result['attempt']['attempt']); $this->assertEquals($this->student->id, $result['attempt']['userid']); $this->assertEquals($quiz->id, $result['attempt']['quiz']); $this->assertCount(0, $result['warnings']); $attemptid = $result['attempt']['id']; // We are good, try to start a new attempt now. try { mod_quiz_external::start_attempt($quiz->id, array(array("name" => "quizpassword", "value" => 'abc'))); $this->fail('Exception expected due to attempt not finished.'); } catch (moodle_quiz_exception $e) { $this->assertEquals('attemptstillinprogress', $e->errorcode); } // Finish the started attempt. // Process some responses from the student. $timenow = time(); $attemptobj = quiz_attempt::create($attemptid); $tosubmit = array(1 => array('answer' => '3.14')); $attemptobj->process_submitted_actions($timenow, false, $tosubmit); // Finish the attempt. $attemptobj = quiz_attempt::create($attemptid); $this->assertTrue($attemptobj->has_response_to_at_least_one_graded_question()); $attemptobj->process_finish($timenow, false); // We should be able to start a new attempt. $result = mod_quiz_external::start_attempt($quiz->id, array(array("name" => "quizpassword", "value" => 'abc'))); $result = external_api::clean_returnvalue(mod_quiz_external::start_attempt_returns(), $result); $this->assertEquals(2, $result['attempt']['attempt']); $this->assertEquals($this->student->id, $result['attempt']['userid']); $this->assertEquals($quiz->id, $result['attempt']['quiz']); $this->assertCount(0, $result['warnings']); // Test user with no capabilities. // We need a explicit prohibit since this capability is only defined in authenticated user and guest roles. assign_capability('mod/quiz:attempt', CAP_PROHIBIT, $this->studentrole->id, $context->id); // Empty all the caches that may be affected by this change. accesslib_clear_all_caches_for_unit_testing(); course_modinfo::clear_instance_cache(); try { mod_quiz_external::start_attempt($quiz->id); $this->fail('Exception expected due to missing capability.'); } catch (required_capability_exception $e) { $this->assertEquals('nopermissions', $e->errorcode); } }
/** * Utility method to submit an attempt on a quiz. * @param $quiz * @param $user * @param $answers * @return testable_assign */ private function submit_quiz_attempt($quiz, $user, $answers) { // Create a quiz attempt for the user. $quizobj = quiz::create($quiz->id, $user->id); // Set up and start an attempt. $quba = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context()); $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour); $timenow = time(); $attempt = quiz_create_attempt($quizobj, 1, false, $timenow, false, $user->id); quiz_start_new_attempt($quizobj, $quba, $attempt, 1, $timenow); quiz_attempt_save_started($quizobj, $quba, $attempt); $attemptobj = quiz_attempt::create($attempt->id); $attemptobj->process_submitted_actions($timenow, false, $answers); $timefinish = time(); // Finish the attempt. $attemptobj->process_finish($timefinish, false); return $timefinish; }
/** * Checks whether the current user is allowed to view a file uploaded in a quiz. * Teachers can view any from their courses, students can only view their own. * * @param int $attemptuniqueid int attempt id * @param int $questionid int question id * @return bool to indicate access granted or denied */ function quiz_check_file_access($attemptuniqueid, $questionid, $context = null) { global $USER, $DB, $CFG; require_once(dirname(__FILE__).'/attemptlib.php'); require_once(dirname(__FILE__).'/locallib.php'); $attempt = $DB->get_record('quiz_attempts', array('uniqueid' => $attemptuniqueid)); $attemptobj = quiz_attempt::create($attempt->id); // does question exist? if (!$question = $DB->get_record('question', array('id' => $questionid))) { return false; } if ($context === null) { $quiz = $DB->get_record('quiz', array('id' => $attempt->quiz)); $cm = get_coursemodule_from_id('quiz', $quiz->id); $context = get_context_instance(CONTEXT_MODULE, $cm->id); } // Load those questions and the associated states. $attemptobj->load_questions(array($questionid)); $attemptobj->load_question_states(array($questionid)); // obtain state $state = $attemptobj->get_question_state($questionid); // obtain questoin $question = $attemptobj->get_question($questionid); // access granted if the current user submitted this file if ($attempt->userid != $USER->id) { return false; } // access granted if the current user has permission to grade quizzes in this course if (!(has_capability('mod/quiz:viewreports', $context) || has_capability('mod/quiz:grade', $context))) { return false; } return array($question, $state, array()); }
function emarking_insert_user_answers($choices, $user, $attemptid) { global $DB; $timenow = time(); $transaction = $DB->start_delegated_transaction(); $attemptobj = quiz_attempt::create($attemptid); $quizobj = $attemptobj->get_quizobj(); $quba = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context()); $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour); $answers = array(); $current = 0; foreach ($attemptobj->get_slots('all') as $k => $slot) { $qa = $attemptobj->get_question_attempt($slot); $currentchoice = 0; foreach ($qa->get_question()->get_order($qa) as $index => $questionid) { $qans = $qa->get_question()->answers[$questionid]; if ($currentchoice == $choices[$current]) { $answers[$slot] = array('answer' => clean_param($qans->answer, PARAM_NOTAGS)); } $currentchoice++; } $current++; } // Don't log - we will end with a redirect to a page that is logged. try { $attemptobj->process_submitted_actions($timenow, false, $answers); } catch (question_out_of_sequence_exception $e) { print_error('submissionoutofsequencefriendlymessage', 'question', $attemptobj->attempt_url(null, $thispage)); } catch (Exception $e) { // This sucks, if we display our own custom error message, there is no way // to display the original stack trace. $debuginfo = ''; if (!empty($e->debuginfo)) { $debuginfo = $e->debuginfo; } print_error('errorprocessingresponses', 'question', $attemptobj->attempt_url(null, $thispage), $e->getMessage(), $debuginfo); } // Send the user to the review page. $DB->commit_delegated_transaction($transaction); }
/** * Deals with data coming in from the grading pop up * * @param object $data the form data * @param $params * @return mixed true on success or an error. */ public function process_data($data, $params) { global $DB; // Get all attempts on all questions that were unmarked. // Slight chance that someone else will have marked the questions since this user opened // the pop up, which could lead to these grades being ignored, or the other person's // being overwritten. Not much we can do about that. $questionattempts = $this->get_question_attempts($params); // We will have duplicates as there could be multiple questions per attempt. $processedattempts = array(); // This will get all of the attempts to pull the relevant data from all the POST stuff // and process it. The quiz adds lots of prefix stuff, so we won't have collisions. foreach ($questionattempts as $attempt) { $id = $attempt->quizattemptid; if (isset($processedattempts[$id])) { continue; } $processedattempts[$id] = quiz_attempt::create($id); $transaction = $DB->start_delegated_transaction(); $processedattempts[$id]->process_all_actions(time()); $transaction->allow_commit(); } return true; }
/** * Create a quiz with a single question with variants and walk through quiz attempts. * * @dataProvider get_correct_response_for_variants */ public function test_quiz_with_question_with_variants_attempt_walkthrough($variantno, $correctresponse, $done = false) { global $SITE; $this->resetAfterTest($done); $this->setAdminUser(); if ($this->quizwithvariants === null) { // Make a quiz. $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz'); $this->quizwithvariants = $quizgenerator->create_instance(array('course'=>$SITE->id, 'questionsperpage' => 0, 'grade' => 100.0, 'sumgrades' => 1)); $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question'); $cat = $questiongenerator->create_question_category(); $calc = $questiongenerator->create_question('calculatedsimple', 'sumwithvariants', array('category' => $cat->id)); quiz_add_quiz_question($calc->id, $this->quizwithvariants, 0); } // Make a new user to do the quiz. $user1 = $this->getDataGenerator()->create_user(); $this->setUser($user1); $quizobj = quiz::create($this->quizwithvariants->id, $user1->id); // Start the attempt. $quba = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context()); $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour); $timenow = time(); $attempt = quiz_create_attempt($quizobj, 1, false, $timenow); // Select variant. quiz_start_new_attempt($quizobj, $quba, $attempt, 1, $timenow, array(), array(1 => $variantno)); $this->assertEquals('1,0', $attempt->layout); quiz_attempt_save_started($quizobj, $quba, $attempt); // Process some responses from the student. $attemptobj = quiz_attempt::create($attempt->id); $tosubmit = array(1 => array('answer' => $correctresponse)); $attemptobj->process_submitted_actions($timenow, false, $tosubmit); // Finish the attempt. $attemptobj = quiz_attempt::create($attempt->id); $attemptobj->process_finish($timenow, false); // Re-load quiz attempt data. $attemptobj = quiz_attempt::create($attempt->id); // Check that results are stored as expected. $this->assertEquals(1, $attemptobj->get_attempt_number()); $this->assertEquals(1, $attemptobj->get_sum_marks()); $this->assertEquals(true, $attemptobj->is_finished()); $this->assertEquals($timenow, $attemptobj->get_submitted_date()); $this->assertEquals($user1->id, $attemptobj->get_userid()); // Check quiz grades. $grades = quiz_get_user_grades($this->quizwithvariants, $user1->id); $grade = array_shift($grades); $this->assertEquals(100.0, $grade->rawgrade); // Check grade book. $gradebookgrades = grade_get_grades($SITE->id, 'mod', 'quiz', $this->quizwithvariants->id, $user1->id); $gradebookitem = array_shift($gradebookgrades->items); $gradebookgrade = array_shift($gradebookitem->grades); $this->assertEquals(100, $gradebookgrade->grade); }
*/ require_once dirname(__FILE__) . '/../../config.php'; require_once $CFG->dirroot . '/mod/quiz/locallib.php'; require_once $CFG->dirroot . '/mod/quiz/report/reportlib.php'; $attemptid = required_param('attempt', PARAM_INT); $page = optional_param('page', 0, PARAM_INT); $showall = optional_param('showall', 0, PARAM_BOOL); $url = new moodle_url('/mod/quiz/review.php', array('attempt' => $attemptid)); if ($page !== 0) { $url->param('page', $page); } if ($showall !== 0) { $url->param('showall', $showall); } $PAGE->set_url($url); $attemptobj = quiz_attempt::create($attemptid); /// Check login. require_login($attemptobj->get_course(), false, $attemptobj->get_cm()); $attemptobj->check_review_capability(); /// Create an object to manage all the other (non-roles) access rules. $accessmanager = $attemptobj->get_access_manager(time()); $options = $attemptobj->get_review_options(); // Check permissions. if ($attemptobj->is_own_attempt()) { if (!$attemptobj->is_finished()) { redirect($attemptobj->attempt_url(0, $page)); } else { if (!$options->responses) { $accessmanager->back_to_view_page($attemptobj->is_preview_user(), $accessmanager->cannot_review_message($options)); } }
public function test_attempt_abandoned() { list($quizobj, $quba, $attempt) = $this->prepare_quiz_data(); $attemptobj = quiz_attempt::create($attempt->id); // Catch the event. $sink = $this->redirectEvents(); $timefinish = time(); $attemptobj->process_abandon($timefinish, false); $events = $sink->get_events(); $sink->close(); $this->assertCount(1, $events); $event = $events[0]; $this->assertInstanceOf('\\mod_quiz\\event\\attempt_abandoned', $event); $this->assertEquals('quiz_attempts', $event->objecttable); $this->assertEquals($quizobj->get_context(), $event->get_context()); $this->assertEquals($attempt->userid, $event->relateduserid); // Submitterid should be the user, but as we are in PHP Unit, CLI_SCRIPT is set to true which sets null in submitterid. $this->assertEquals(null, $event->other['submitterid']); $this->assertEquals('quiz_attempt_abandoned', $event->get_legacy_eventname()); $legacydata = new stdClass(); $legacydata->component = 'mod_quiz'; $legacydata->attemptid = (string) $attempt->id; $legacydata->timestamp = $timefinish; $legacydata->userid = $attempt->userid; $legacydata->cmid = $quizobj->get_cmid(); $legacydata->courseid = $quizobj->get_courseid(); $legacydata->quizid = $quizobj->get_quizid(); $legacydata->submitterid = null; // Should be the user, but PHP Unit complains... $this->assertEventLegacyData($legacydata, $event); $this->assertEventContextNotUsed($event); }
/** * Return access information for a given attempt in a quiz. * * @param int $quizid quiz instance id * @param int $attemptid attempt id, 0 for the user last attempt if exists * @return array of warnings and the access information * @since Moodle 3.1 * @throws moodle_quiz_exception */ public static function get_attempt_access_information($quizid, $attemptid = 0) { global $DB, $USER; $warnings = array(); $params = array('quizid' => $quizid, 'attemptid' => $attemptid); $params = self::validate_parameters(self::get_attempt_access_information_parameters(), $params); list($quiz, $course, $cm, $context) = self::validate_quiz($params['quizid']); $attempttocheck = 0; if (!empty($params['attemptid'])) { $attemptobj = quiz_attempt::create($params['attemptid']); if ($attemptobj->get_userid() != $USER->id) { throw new moodle_quiz_exception($attemptobj->get_quizobj(), 'notyourattempt'); } $attempttocheck = $attemptobj->get_attempt(); } // Access manager now. $quizobj = quiz::create($cm->instance, $USER->id); $ignoretimelimits = has_capability('mod/quiz:ignoretimelimits', $context, null, false); $timenow = time(); $accessmanager = new quiz_access_manager($quizobj, $timenow, $ignoretimelimits); $attempts = quiz_get_user_attempts($quiz->id, $USER->id, 'finished', true); $lastfinishedattempt = end($attempts); if ($unfinishedattempt = quiz_get_user_attempt_unfinished($quiz->id, $USER->id)) { $attempts[] = $unfinishedattempt; // Check if the attempt is now overdue. In that case the state will change. $quizobj->create_attempt_object($unfinishedattempt)->handle_if_time_expired(time(), false); if ($unfinishedattempt->state != quiz_attempt::IN_PROGRESS and $unfinishedattempt->state != quiz_attempt::OVERDUE) { $lastfinishedattempt = $unfinishedattempt; } } $numattempts = count($attempts); if (!$attempttocheck) { $attempttocheck = $unfinishedattempt ? $unfinishedattempt : $lastfinishedattempt; } $result = array(); $result['isfinished'] = $accessmanager->is_finished($numattempts, $lastfinishedattempt); $result['preventnewattemptreasons'] = $accessmanager->prevent_new_attempt($numattempts, $lastfinishedattempt); if ($attempttocheck) { $endtime = $accessmanager->get_end_time($attempttocheck); $result['endtime'] = $endtime === false ? 0 : $endtime; $attemptid = $unfinishedattempt ? $unfinishedattempt->id : null; $result['ispreflightcheckrequired'] = $accessmanager->is_preflight_check_required($attemptid); } $result['warnings'] = $warnings; return $result; }
public static function print_attempt($attempt_id) { //create a new attempt object from the given attempt ID $attempt = quiz_attempt::create($attempt_id); //get the coursemodule for the given attempt $cm = $attempt->get_cm(); //and ensure the user can access this context require_login($attempt->get_course(), false, $cm); //get the quiz object from the attempt $quiz = $attempt->get_quiz(); //if the quiz doesn't allow printable PDFs, throw an error if (!$quiz->allowprint) { print_error('nopermissiontoshow'); } //set up the page for PDF rendering self::set_up_pdf(); //and get the unique ID from the attempt $quba_id = $attempt->get_uniqueid(); //get the current context from the coursemodule $context = context_module::instance($cm->id); //create a new print helper $print_helper = new self($quiz, $context); //and use it to print the given quiz $print_helper->print_quba($quba_id, quiz_papercopy_batch_mode::NORMAL, false, true); }