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());
 }
Example #2
0
 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);
 }
Example #5
0
 /**
  * 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'));
 }
Example #6
0
 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);
 }
Example #7
0
 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);
 }
Example #8
0
 /**
  * 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();
 }
Example #10
0
/**
 * 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);
}
Example #11
0
$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);
     }
 }
Example #13
0
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);
 }
Example #15
0
 /**
  * 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;
 }
Example #17
0
/**
 * 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());
}
Example #18
0
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);
    }
Example #21
0
 */
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);
 }
Example #23
0
 /**
  * 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);
 }