Differences Between: [Versions 310 and 402] [Versions 311 and 402] [Versions 39 and 402] [Versions 400 and 402] [Versions 401 and 402]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 namespace mod_quiz; 18 19 use core_question_generator; 20 use mod_quiz\task\update_overdue_attempts; 21 use mod_quiz_generator; 22 use question_engine; 23 use mod_quiz\quiz_settings; 24 25 defined('MOODLE_INTERNAL') || die(); 26 27 global $CFG; 28 require_once($CFG->dirroot.'/group/lib.php'); 29 30 /** 31 * Unit tests for quiz attempt overdue handling 32 * 33 * @package mod_quiz 34 * @category test 35 * @copyright 2012 Matt Petro 36 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 37 */ 38 class attempts_test extends \advanced_testcase { 39 40 /** 41 * Test the functions quiz_update_open_attempts(), get_list_of_overdue_attempts() and 42 * update_overdue_attempts(). 43 */ 44 public function test_bulk_update_functions() { 45 global $DB; 46 $this->resetAfterTest(); 47 $this->setAdminUser(); 48 49 // Setup course, user and groups 50 51 $course = $this->getDataGenerator()->create_course(); 52 $user1 = $this->getDataGenerator()->create_user(); 53 $studentrole = $DB->get_record('role', ['shortname' => 'student']); 54 $this->assertNotEmpty($studentrole); 55 $this->assertTrue(enrol_try_internal_enrol($course->id, $user1->id, $studentrole->id)); 56 $group1 = $this->getDataGenerator()->create_group(['courseid' => $course->id]); 57 $group2 = $this->getDataGenerator()->create_group(['courseid' => $course->id]); 58 $group3 = $this->getDataGenerator()->create_group(['courseid' => $course->id]); 59 $this->assertTrue(groups_add_member($group1, $user1)); 60 $this->assertTrue(groups_add_member($group2, $user1)); 61 62 $usertimes = []; 63 64 /** @var mod_quiz_generator $quizgenerator */ 65 $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz'); 66 67 // Basic quiz settings 68 69 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600]); 70 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 71 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 72 $usertimes[$attemptid] = ['timeclose' => 1200, 'timelimit' => 600, 'message' => 'Test1A', 'time1000state' => 'finished']; 73 74 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 1800]); 75 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 76 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 77 $usertimes[$attemptid] = ['timeclose' => 1200, 'timelimit' => 1800, 'message' => 'Test1B', 'time1000state' => 'inprogress']; 78 79 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 0]); 80 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 81 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 82 $usertimes[$attemptid] = ['timeclose' => 1200, 'timelimit' => 0, 'message' => 'Test1C', 'time1000state' => 'inprogress']; 83 84 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 0, 'timelimit' => 600]); 85 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 86 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 87 $usertimes[$attemptid] = ['timeclose' => 0, 'timelimit' => 600, 'message' => 'Test1D', 'time1000state' => 'finished']; 88 89 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 0, 'timelimit' => 0]); 90 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 91 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 92 $usertimes[$attemptid] = ['timeclose' => 0, 'timelimit' => 0, 'message' => 'Test1E', 'time1000state' => 'inprogress']; 93 94 // Group overrides 95 96 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 0]); 97 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 98 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 99 $DB->insert_record('quiz_overrides', 100 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1300, 'timelimit' => null]); 101 $usertimes[$attemptid] = ['timeclose' => 1300, 'timelimit' => 0, 'message' => 'Test2A', 'time1000state' => 'inprogress']; 102 103 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 0]); 104 $DB->insert_record('quiz_overrides', 105 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1100, 'timelimit' => null]); 106 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 107 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 108 $usertimes[$attemptid] = ['timeclose' => 1100, 'timelimit' => 0, 'message' => 'Test2B', 'time1000state' => 'inprogress']; 109 110 $quiz = $quizgenerator->create_instance( 111 ['course' => $course->id, 'timeclose' => 0, 'timelimit' => 600, 'overduehandling' => 'autoabandon']); 112 $DB->insert_record('quiz_overrides', 113 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => null, 'timelimit' => 700]); 114 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 115 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 116 $usertimes[$attemptid] = ['timeclose' => 0, 'timelimit' => 700, 'message' => 'Test2C', 'time1000state' => 'abandoned']; 117 118 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 0, 'timelimit' => 600]); 119 $DB->insert_record('quiz_overrides', 120 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => null, 'timelimit' => 500]); 121 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 122 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 123 $usertimes[$attemptid] = ['timeclose' => 0, 'timelimit' => 500, 'message' => 'Test2D', 'time1000state' => 'finished']; 124 125 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 0, 'timelimit' => 600]); 126 $DB->insert_record('quiz_overrides', 127 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => null, 'timelimit' => 0]); 128 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 129 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 130 $usertimes[$attemptid] = ['timeclose' => 0, 'timelimit' => 0, 'message' => 'Test2E', 'time1000state' => 'inprogress']; 131 132 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600]); 133 $DB->insert_record('quiz_overrides', 134 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1300, 'timelimit' => 500]); 135 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 136 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 137 $usertimes[$attemptid] = ['timeclose' => 1300, 'timelimit' => 500, 'message' => 'Test2F', 'time1000state' => 'finished']; 138 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 139 'timestart' => 1000, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz), 'attempt' => 1]); 140 $usertimes[$attemptid] = ['timeclose' => 1300, 'timelimit' => 500, 'message' => 'Test2G', 'time1000state' => 'inprogress']; 141 142 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600]); 143 $DB->insert_record('quiz_overrides', 144 ['quiz' => $quiz->id, 'groupid' => $group3->id, 'timeclose' => 1300, 'timelimit' => 500]); // User not in group. 145 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 146 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 147 $usertimes[$attemptid] = ['timeclose' => 1200, 'timelimit' => 600, 'message' => 'Test2H', 'time1000state' => 'finished']; 148 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 149 'timestart' => 1000, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz), 'attempt' => 1]); 150 $usertimes[$attemptid] = ['timeclose' => 1200, 'timelimit' => 600, 'message' => 'Test2I', 'time1000state' => 'inprogress']; 151 152 // Multiple group overrides 153 154 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600]); 155 $DB->insert_record('quiz_overrides', 156 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1300, 'timelimit' => 501]); 157 $DB->insert_record('quiz_overrides', 158 ['quiz' => $quiz->id, 'groupid' => $group2->id, 'timeclose' => 1301, 'timelimit' => 500]); 159 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 160 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 161 $usertimes[$attemptid] = ['timeclose' => 1301, 'timelimit' => 501, 'message' => 'Test3A', 'time1000state' => 'finished']; 162 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 163 'timestart' => 1000, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz), 'attempt' => 1]); 164 $usertimes[$attemptid] = ['timeclose' => 1301, 'timelimit' => 501, 'message' => 'Test3B', 'time1000state' => 'inprogress']; 165 166 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600]); 167 $DB->insert_record('quiz_overrides', 168 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1301, 'timelimit' => 500]); 169 $DB->insert_record('quiz_overrides', 170 ['quiz' => $quiz->id, 'groupid' => $group2->id, 'timeclose' => 1300, 'timelimit' => 501]); 171 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 172 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 173 $usertimes[$attemptid] = ['timeclose' => 1301, 'timelimit' => 501, 'message' => 'Test3C', 'time1000state' => 'finished']; 174 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 175 'timestart' => 1000, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz), 'attempt' => 1]); 176 $usertimes[$attemptid] = ['timeclose' => 1301, 'timelimit' => 501, 'message' => 'Test3D', 'time1000state' => 'inprogress']; 177 178 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600, 179 'overduehandling' => 'autoabandon']); 180 $DB->insert_record('quiz_overrides', 181 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1301, 'timelimit' => 500]); 182 $DB->insert_record('quiz_overrides', 183 ['quiz' => $quiz->id, 'groupid' => $group2->id, 'timeclose' => 1300, 'timelimit' => 501]); 184 $DB->insert_record('quiz_overrides', 185 ['quiz' => $quiz->id, 'groupid' => $group3->id, 'timeclose' => 1500, 'timelimit' => 1000]); // User not in group. 186 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 187 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 188 $usertimes[$attemptid] = ['timeclose' => 1301, 'timelimit' => 501, 'message' => 'Test3E', 'time1000state' => 'abandoned']; 189 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 190 'timestart' => 1000, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz), 'attempt' => 1]); 191 $usertimes[$attemptid] = ['timeclose' => 1301, 'timelimit' => 501, 'message' => 'Test3F', 'time1000state' => 'inprogress']; 192 193 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600]); 194 $DB->insert_record('quiz_overrides', 195 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1300, 'timelimit' => 500]); 196 $DB->insert_record('quiz_overrides', 197 ['quiz' => $quiz->id, 'groupid' => $group2->id, 'timeclose' => null, 'timelimit' => 501]); 198 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 199 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 200 $usertimes[$attemptid] = ['timeclose' => 1300, 'timelimit' => 501, 'message' => 'Test3G', 'time1000state' => 'finished']; 201 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 202 'timestart' => 1000, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz), 'attempt' => 1]); 203 $usertimes[$attemptid] = ['timeclose' => 1300, 'timelimit' => 501, 'message' => 'Test3H', 'time1000state' => 'inprogress']; 204 205 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600]); 206 $DB->insert_record('quiz_overrides', 207 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1300, 'timelimit' => 500]); 208 $DB->insert_record('quiz_overrides', 209 ['quiz' => $quiz->id, 'groupid' => $group2->id, 'timeclose' => 1301, 'timelimit' => null]); 210 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 211 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 212 $usertimes[$attemptid] = ['timeclose' => 1301, 'timelimit' => 500, 'message' => 'Test3I', 'time1000state' => 'finished']; 213 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 214 'timestart' => 1000, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz), 'attempt' => 1]); 215 $usertimes[$attemptid] = ['timeclose' => 1301, 'timelimit' => 500, 'message' => 'Test3J', 'time1000state' => 'inprogress']; 216 217 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600]); 218 $DB->insert_record('quiz_overrides', 219 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1300, 'timelimit' => 500]); 220 $DB->insert_record('quiz_overrides', 221 ['quiz' => $quiz->id, 'groupid' => $group2->id, 'timeclose' => 1301, 'timelimit' => 0]); 222 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 223 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 224 $usertimes[$attemptid] = ['timeclose' => 1301, 'timelimit' => 0, 'message' => 'Test3K', 'time1000state' => 'inprogress']; 225 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 226 'timestart' => 1000, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz), 'attempt' => 1]); 227 $usertimes[$attemptid] = ['timeclose' => 1301, 'timelimit' => 0, 'message' => 'Test3L', 'time1000state' => 'inprogress']; 228 229 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600]); 230 $DB->insert_record('quiz_overrides', 231 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1300, 'timelimit' => 500]); 232 $DB->insert_record('quiz_overrides', 233 ['quiz' => $quiz->id, 'groupid' => $group2->id, 'timeclose' => 0, 'timelimit' => 501]); 234 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 235 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 236 $usertimes[$attemptid] = ['timeclose' => 0, 'timelimit' => 501, 'message' => 'Test3M', 'time1000state' => 'finished']; 237 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 238 'timestart' => 1000, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz), 'attempt' => 1]); 239 $usertimes[$attemptid] = ['timeclose' => 0, 'timelimit' => 501, 'message' => 'Test3N', 'time1000state' => 'inprogress']; 240 241 // User overrides 242 243 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600]); 244 $DB->insert_record('quiz_overrides', 245 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1300, 'timelimit' => 700]); 246 $DB->insert_record('quiz_overrides', 247 ['quiz' => $quiz->id, 'userid' => $user1->id, 'timeclose' => 1201, 'timelimit' => 601]); 248 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 249 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 250 $usertimes[$attemptid] = ['timeclose' => 1201, 'timelimit' => 601, 'message' => 'Test4A', 'time1000state' => 'finished']; 251 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 252 'timestart' => 1000, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz), 'attempt' => 1]); 253 $usertimes[$attemptid] = ['timeclose' => 1201, 'timelimit' => 601, 'message' => 'Test4B', 'time1000state' => 'inprogress']; 254 255 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600]); 256 $DB->insert_record('quiz_overrides', 257 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1300, 'timelimit' => 700]); 258 $DB->insert_record('quiz_overrides', 259 ['quiz' => $quiz->id, 'userid' => $user1->id, 'timeclose' => 0, 'timelimit' => 601]); 260 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 261 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 262 $usertimes[$attemptid] = ['timeclose' => 0, 'timelimit' => 601, 'message' => 'Test4C', 'time1000state' => 'finished']; 263 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 264 'timestart' => 1000, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz), 'attempt' => 1]); 265 $usertimes[$attemptid] = ['timeclose' => 0, 'timelimit' => 601, 'message' => 'Test4D', 'time1000state' => 'inprogress']; 266 267 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600]); 268 $DB->insert_record('quiz_overrides', 269 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1300, 'timelimit' => 700]); 270 $DB->insert_record('quiz_overrides', 271 ['quiz' => $quiz->id, 'userid' => $user1->id, 'timeclose' => 1201, 'timelimit' => 0]); 272 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 273 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 274 $usertimes[$attemptid] = ['timeclose' => 1201, 'timelimit' => 0, 'message' => 'Test4E', 'time1000state' => 'inprogress']; 275 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 276 'timestart' => 1000, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz), 'attempt' => 1]); 277 $usertimes[$attemptid] = ['timeclose' => 1201, 'timelimit' => 0, 'message' => 'Test4F', 'time1000state' => 'inprogress']; 278 279 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600, 280 'overduehandling' => 'autoabandon']); 281 $DB->insert_record('quiz_overrides', 282 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1300, 'timelimit' => 700]); 283 $DB->insert_record('quiz_overrides', 284 ['quiz' => $quiz->id, 'userid' => $user1->id, 'timeclose' => null, 'timelimit' => 601]); 285 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 286 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 287 $usertimes[$attemptid] = ['timeclose' => 1300, 'timelimit' => 601, 'message' => 'Test4G', 'time1000state' => 'abandoned']; 288 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 289 'timestart' => 1000, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz), 'attempt' => 1]); 290 $usertimes[$attemptid] = ['timeclose' => 1300, 'timelimit' => 601, 'message' => 'Test4H', 'time1000state' => 'inprogress']; 291 292 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600]); 293 $DB->insert_record('quiz_overrides', 294 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => null, 'timelimit' => 700]); 295 $DB->insert_record('quiz_overrides', 296 ['quiz' => $quiz->id, 'userid' => $user1->id, 'timeclose' => null, 'timelimit' => 601]); 297 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 298 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 299 $usertimes[$attemptid] = ['timeclose' => 1200, 'timelimit' => 601, 'message' => 'Test4I', 'time1000state' => 'finished']; 300 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 301 'timestart' => 1000, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz), 'attempt' => 1]); 302 $usertimes[$attemptid] = ['timeclose' => 1200, 'timelimit' => 601, 'message' => 'Test4J', 'time1000state' => 'inprogress']; 303 304 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600]); 305 $DB->insert_record('quiz_overrides', 306 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1300, 'timelimit' => 700]); 307 $DB->insert_record('quiz_overrides', 308 ['quiz' => $quiz->id, 'userid' => $user1->id, 'timeclose' => 1201, 'timelimit' => null]); 309 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 310 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 311 $usertimes[$attemptid] = ['timeclose' => 1201, 'timelimit' => 700, 'message' => 'Test4K', 'time1000state' => 'finished']; 312 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 313 'timestart' => 1000, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz), 'attempt' => 1]); 314 $usertimes[$attemptid] = ['timeclose' => 1201, 'timelimit' => 700, 'message' => 'Test4L', 'time1000state' => 'inprogress']; 315 316 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600]); 317 $DB->insert_record('quiz_overrides', 318 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1300, 'timelimit' => null]); 319 $DB->insert_record('quiz_overrides', 320 ['quiz' => $quiz->id, 'userid' => $user1->id, 'timeclose' => 1201, 'timelimit' => null]); 321 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 322 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 323 $usertimes[$attemptid] = ['timeclose' => 1201, 'timelimit' => 600, 'message' => 'Test4M', 'time1000state' => 'finished']; 324 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 325 'timestart' => 1000, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz), 'attempt' => 1]); 326 $usertimes[$attemptid] = ['timeclose' => 1201, 'timelimit' => 600, 'message' => 'Test4N', 'time1000state' => 'inprogress']; 327 328 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600]); 329 $DB->insert_record('quiz_overrides', 330 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1300, 'timelimit' => 700]); 331 $DB->insert_record('quiz_overrides', 332 ['quiz' => $quiz->id, 'userid' => 0, 'timeclose' => 1201, 'timelimit' => 601]); // Not user. 333 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 334 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 335 $usertimes[$attemptid] = ['timeclose' => 1300, 'timelimit' => 700, 'message' => 'Test4O', 'time1000state' => 'finished']; 336 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 337 'timestart' => 1000, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz), 'attempt' => 1]); 338 $usertimes[$attemptid] = ['timeclose' => 1300, 'timelimit' => 700, 'message' => 'Test4P', 'time1000state' => 'inprogress']; 339 340 // Attempt state overdue 341 342 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600, 343 'overduehandling' => 'graceperiod', 'graceperiod' => 250]); 344 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'overdue', 345 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 346 $usertimes[$attemptid] = ['timeclose' => 1200, 'timelimit' => 600, 'message' => 'Test5A', 'time1000state' => 'overdue']; 347 348 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 0, 'timelimit' => 600, 349 'overduehandling' => 'graceperiod', 'graceperiod' => 250]); 350 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'overdue', 351 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 352 $usertimes[$attemptid] = ['timeclose' => 0, 'timelimit' => 600, 'message' => 'Test5B', 'time1000state' => 'overdue']; 353 354 // Compute expected end time for each attempt. 355 foreach ($usertimes as $attemptid => $times) { 356 $attempt = $DB->get_record('quiz_attempts', ['id' => $attemptid], '*', MUST_EXIST); 357 358 if ($times['timeclose'] > 0 && $times['timelimit'] > 0) { 359 $usertimes[$attemptid]['timedue'] = min($times['timeclose'], $attempt->timestart + $times['timelimit']); 360 } else if ($times['timeclose'] > 0) { 361 $usertimes[$attemptid]['timedue'] = $times['timeclose']; 362 } else if ($times['timelimit'] > 0) { 363 $usertimes[$attemptid]['timedue'] = $attempt->timestart + $times['timelimit']; 364 } 365 } 366 367 // 368 // Test quiz_update_open_attempts(). 369 // 370 371 quiz_update_open_attempts(['courseid' => $course->id]); 372 foreach ($usertimes as $attemptid => $times) { 373 $attempt = $DB->get_record('quiz_attempts', ['id' => $attemptid], '*', MUST_EXIST); 374 375 if ($attempt->state == 'overdue') { 376 $graceperiod = $DB->get_field('quiz', 'graceperiod', ['id' => $attempt->quiz]); 377 } else { 378 $graceperiod = 0; 379 } 380 if (isset($times['timedue'])) { 381 $this->assertEquals($times['timedue'] + $graceperiod, $attempt->timecheckstate, $times['message']); 382 } else { 383 $this->assertNull($attempt->timecheckstate, $times['message']); 384 } 385 } 386 387 // 388 // Test get_list_of_overdue_attempts(). 389 // 390 391 $overduehander = new update_overdue_attempts(); 392 393 $attempts = $overduehander->get_list_of_overdue_attempts(100000); // way in the future 394 $count = 0; 395 foreach ($attempts as $attempt) { 396 $this->assertTrue(isset($usertimes[$attempt->id])); 397 $times = $usertimes[$attempt->id]; 398 $this->assertEquals($times['timeclose'], $attempt->usertimeclose, $times['message']); 399 $this->assertEquals($times['timelimit'], $attempt->usertimelimit, $times['message']); 400 $count++; 401 402 } 403 $attempts->close(); 404 $this->assertEquals($DB->count_records_select('quiz_attempts', 'timecheckstate IS NOT NULL'), $count); 405 406 $attempts = $overduehander->get_list_of_overdue_attempts(0); // before all attempts 407 $count = 0; 408 foreach ($attempts as $attempt) { 409 $count++; 410 } 411 $attempts->close(); 412 $this->assertEquals(0, $count); 413 414 // 415 // Test update_overdue_attempts(). 416 // 417 418 [$count, $quizcount] = $overduehander->update_all_overdue_attempts(1000, 940); 419 420 $attempts = $DB->get_records('quiz_attempts', null, 'quiz, userid, attempt', 421 'id, quiz, userid, attempt, state, timestart, timefinish, timecheckstate'); 422 foreach ($attempts as $attempt) { 423 $this->assertTrue(isset($usertimes[$attempt->id])); 424 $times = $usertimes[$attempt->id]; 425 $this->assertEquals($times['time1000state'], $attempt->state, $times['message']); 426 switch ($times['time1000state']) { 427 case 'finished': 428 $this->assertEquals($times['timedue'], $attempt->timefinish, $times['message']); 429 $this->assertNull($attempt->timecheckstate, $times['message']); 430 break; 431 432 case 'overdue': 433 $this->assertEquals(0, $attempt->timefinish, $times['message']); 434 $graceperiod = $DB->get_field('quiz', 'graceperiod', ['id' => $attempt->quiz]); 435 $this->assertEquals($times['timedue'] + $graceperiod, $attempt->timecheckstate, $times['message']); 436 break; 437 438 case 'abandoned': 439 $this->assertEquals(0, $attempt->timefinish, $times['message']); 440 $this->assertNull($attempt->timecheckstate, $times['message']); 441 break; 442 } 443 } 444 445 $this->assertEquals(19, $count); 446 $this->assertEquals(19, $quizcount); 447 } 448 449 /** 450 * Make any old question usage for a quiz. 451 * 452 * The attempts used in test_bulk_update_functions must have some 453 * question usage to store in uniqueid, but they don't have to be 454 * very realistic. 455 * 456 * @param \stdClass $quiz 457 * @return int question usage id. 458 */ 459 protected function usage_id(\stdClass $quiz): int { 460 $quba = question_engine::make_questions_usage_by_activity('mod_quiz', 461 \context_module::instance($quiz->cmid)); 462 $quba->set_preferred_behaviour('deferredfeedback'); 463 question_engine::save_questions_usage_by_activity($quba); 464 return $quba->get_id(); 465 } 466 467 /** 468 * Test the group event handlers 469 */ 470 public function test_group_event_handlers() { 471 global $DB; 472 473 $this->resetAfterTest(); 474 475 $this->setAdminUser(); 476 477 // Setup course, user and groups 478 479 $course = $this->getDataGenerator()->create_course(); 480 $user1 = $this->getDataGenerator()->create_user(); 481 $studentrole = $DB->get_record('role', ['shortname' => 'student']); 482 $this->assertNotEmpty($studentrole); 483 $this->assertTrue(enrol_try_internal_enrol($course->id, $user1->id, $studentrole->id)); 484 $group1 = $this->getDataGenerator()->create_group(['courseid' => $course->id]); 485 $group2 = $this->getDataGenerator()->create_group(['courseid' => $course->id]); 486 $this->assertTrue(groups_add_member($group1, $user1)); 487 $this->assertTrue(groups_add_member($group2, $user1)); 488 489 /** @var mod_quiz_generator $quizgenerator */ 490 $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz'); 491 492 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 0]); 493 494 // add a group1 override 495 $DB->insert_record('quiz_overrides', 496 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1300, 'timelimit' => null]); 497 498 // add an attempt 499 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 500 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 501 502 // update timecheckstate 503 quiz_update_open_attempts(['quizid' => $quiz->id]); 504 $this->assertEquals(1300, $DB->get_field('quiz_attempts', 'timecheckstate', ['id' => $attemptid])); 505 506 // remove from group 507 $this->assertTrue(groups_remove_member($group1, $user1)); 508 $this->assertEquals(1200, $DB->get_field('quiz_attempts', 'timecheckstate', ['id' => $attemptid])); 509 510 // add back to group 511 $this->assertTrue(groups_add_member($group1, $user1)); 512 $this->assertEquals(1300, $DB->get_field('quiz_attempts', 'timecheckstate', ['id' => $attemptid])); 513 514 // delete group 515 groups_delete_group($group1); 516 $this->assertEquals(1200, $DB->get_field('quiz_attempts', 'timecheckstate', ['id' => $attemptid])); 517 $this->assertEquals(0, $DB->count_records('quiz_overrides', ['quiz' => $quiz->id])); 518 519 // add a group2 override 520 $DB->insert_record('quiz_overrides', 521 ['quiz' => $quiz->id, 'groupid' => $group2->id, 'timeclose' => 1400, 'timelimit' => null]); 522 quiz_update_open_attempts(['quizid' => $quiz->id]); 523 $this->assertEquals(1400, $DB->get_field('quiz_attempts', 'timecheckstate', ['id' => $attemptid])); 524 525 // delete user1 from all groups 526 groups_delete_group_members($course->id, $user1->id); 527 $this->assertEquals(1200, $DB->get_field('quiz_attempts', 'timecheckstate', ['id' => $attemptid])); 528 529 // add back to group2 530 $this->assertTrue(groups_add_member($group2, $user1)); 531 $this->assertEquals(1400, $DB->get_field('quiz_attempts', 'timecheckstate', ['id' => $attemptid])); 532 533 // delete everyone from all groups 534 groups_delete_group_members($course->id); 535 $this->assertEquals(1200, $DB->get_field('quiz_attempts', 'timecheckstate', ['id' => $attemptid])); 536 } 537 538 /** 539 * Test the functions quiz_create_attempt_handling_errors 540 */ 541 public function test_quiz_create_attempt_handling_errors() { 542 $this->resetAfterTest(true); 543 $this->setAdminUser(); 544 545 // Make a quiz. 546 $course = $this->getDataGenerator()->create_course(); 547 $user1 = $this->getDataGenerator()->create_user(); 548 $student = $this->getDataGenerator()->create_user(); 549 $this->getDataGenerator()->enrol_user($student->id, $course->id, 'student'); 550 /** @var mod_quiz_generator $quizgenerator */ 551 $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz'); 552 /** @var core_question_generator $questiongenerator */ 553 $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question'); 554 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'questionsperpage' => 0, 'grade' => 100.0, 555 'sumgrades' => 2]); 556 // Create questions. 557 $cat = $questiongenerator->create_question_category(); 558 $saq = $questiongenerator->create_question('shortanswer', null, ['category' => $cat->id]); 559 $numq = $questiongenerator->create_question('numerical', null, ['category' => $cat->id]); 560 // Add them to the quiz. 561 quiz_add_quiz_question($saq->id, $quiz); 562 quiz_add_quiz_question($numq->id, $quiz); 563 $quizobj = quiz_settings::create($quiz->id, $user1->id); 564 $quba = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context()); 565 $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour); 566 $timenow = time(); 567 // Create an attempt. 568 $attempt = quiz_create_attempt($quizobj, 1, null, $timenow, false, $user1->id); 569 quiz_start_new_attempt($quizobj, $quba, $attempt, 1, $timenow); 570 quiz_attempt_save_started($quizobj, $quba, $attempt); 571 $result = quiz_create_attempt_handling_errors($attempt->id, $quiz->cmid); 572 $this->assertEquals($result->get_attemptid(), $attempt->id); 573 try { 574 $result = quiz_create_attempt_handling_errors($attempt->id, 9999); 575 $this->fail('Exception expected due to invalid course module id.'); 576 } catch (\moodle_exception $e) { 577 $this->assertEquals('invalidcoursemodule', $e->errorcode); 578 } 579 try { 580 quiz_create_attempt_handling_errors(9999, $result->get_cmid()); 581 $this->fail('Exception expected due to quiz content change.'); 582 } catch (\moodle_exception $e) { 583 $this->assertEquals('attempterrorcontentchange', $e->errorcode); 584 } 585 try { 586 quiz_create_attempt_handling_errors(9999); 587 $this->fail('Exception expected due to invalid quiz attempt id.'); 588 } catch (\moodle_exception $e) { 589 $this->assertEquals('attempterrorinvalid', $e->errorcode); 590 } 591 // Set up as normal user without permission to view preview. 592 $this->setUser($student->id); 593 try { 594 quiz_create_attempt_handling_errors(9999, $result->get_cmid()); 595 $this->fail('Exception expected due to quiz content change for user without permission.'); 596 } catch (\moodle_exception $e) { 597 $this->assertEquals('attempterrorcontentchangeforuser', $e->errorcode); 598 } 599 try { 600 quiz_create_attempt_handling_errors($attempt->id, 9999); 601 $this->fail('Exception expected due to invalid course module id for user without permission.'); 602 } catch (\moodle_exception $e) { 603 $this->assertEquals('invalidcoursemodule', $e->errorcode); 604 } 605 } 606 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body