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 /** 18 * A test helper trait. 19 * 20 * @package quizaccess_seb 21 * @author Andrew Madden <andrewmadden@catalyst-au.net> 22 * @copyright 2019 Catalyst IT 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 use mod_quiz\local\access_rule_base; 27 use mod_quiz\quiz_attempt; 28 use quizaccess_seb\seb_access_manager; 29 use quizaccess_seb\settings_provider; 30 31 defined('MOODLE_INTERNAL') || die(); 32 33 global $CFG; 34 require_once($CFG->dirroot . "/mod/quiz/accessrule/seb/rule.php"); // Include plugin rule class. 35 require_once($CFG->dirroot . "/mod/quiz/mod_form.php"); // Include plugin rule class. 36 37 /** 38 * A test helper trait. It has some common helper methods. 39 * 40 * @copyright 2020 Catalyst IT 41 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 42 */ 43 trait quizaccess_seb_test_helper_trait { 44 45 /** @var \stdClass $course Test course to contain quiz. */ 46 protected $course; 47 48 /** @var \stdClass $quiz A test quiz. */ 49 protected $quiz; 50 51 /** @var \stdClass $user A test logged-in user. */ 52 protected $user; 53 54 /** 55 * Assign a capability to $USER 56 * The function creates a student $USER if $USER->id is empty 57 * 58 * @param string $capability Capability name. 59 * @param int $contextid Context ID. 60 * @param int $roleid Role ID. 61 * @return int The role id - mainly returned for creation, so calling function can reuse it. 62 */ 63 protected function assign_user_capability($capability, $contextid, $roleid = null) { 64 global $USER; 65 66 // Create a new student $USER if $USER doesn't exist. 67 if (empty($USER->id)) { 68 $user = $this->getDataGenerator()->create_user(); 69 $this->setUser($user); 70 } 71 72 if (empty($roleid)) { 73 $roleid = \create_role('Dummy role', 'dummyrole', 'dummy role description'); 74 } 75 76 \assign_capability($capability, CAP_ALLOW, $roleid, $contextid); 77 78 \role_assign($roleid, $USER->id, $contextid); 79 80 \accesslib_clear_all_caches_for_unit_testing(); 81 82 return $roleid; 83 } 84 85 /** 86 * Strip the seb_ prefix from each setting key. 87 * 88 * @param \stdClass $settings Object containing settings. 89 * @return \stdClass The modified settings object. 90 */ 91 protected function strip_all_prefixes(\stdClass $settings) : \stdClass { 92 $newsettings = new \stdClass(); 93 foreach ($settings as $name => $setting) { 94 $newname = preg_replace("/^seb_/", "", $name); 95 $newsettings->$newname = $setting; // Add new key. 96 } 97 return $newsettings; 98 } 99 100 /** 101 * Creates a file in the user draft area. 102 * 103 * @param string $xml 104 * @return int The user draftarea id 105 */ 106 protected function create_test_draftarea_file(string $xml) : int { 107 global $USER; 108 109 $itemid = 0; 110 $usercontext = \context_user::instance($USER->id); 111 $filerecord = [ 112 'contextid' => \context_user::instance($USER->id)->id, 113 'component' => 'user', 114 'filearea' => 'draft', 115 'itemid' => $itemid, 116 'filepath' => '/', 117 'filename' => 'test.xml' 118 ]; 119 120 $fs = get_file_storage(); 121 $fs->create_file_from_string($filerecord, $xml); 122 123 $draftitemid = 0; 124 file_prepare_draft_area($draftitemid, $usercontext->id, 'user', 'draft', 0); 125 126 return $draftitemid; 127 } 128 129 /** 130 * Create a file in a modules filearea. 131 * 132 * @param string $xml XML content of the file. 133 * @param string $cmid Course module id. 134 * @return int Item ID of file. 135 */ 136 protected function create_module_test_file(string $xml, string $cmid) : int { 137 $itemid = 0; 138 $fs = get_file_storage(); 139 $filerecord = [ 140 'contextid' => \context_module::instance($cmid)->id, 141 'component' => 'quizaccess_seb', 142 'filearea' => 'filemanager_sebconfigfile', 143 'itemid' => $itemid, 144 'filepath' => '/', 145 'filename' => 'test.xml' 146 ]; 147 $fs->create_file_from_string($filerecord, $xml); 148 return $itemid; 149 } 150 151 /** 152 * Create a test quiz for the specified course. 153 * 154 * @param \stdClass $course 155 * @param int $requiresafeexambrowser How to use SEB for this quiz? 156 * @return array 157 */ 158 protected function create_test_quiz($course, $requiresafeexambrowser = settings_provider::USE_SEB_NO) { 159 $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz'); 160 161 $quiz = $quizgenerator->create_instance([ 162 'course' => $course->id, 163 'questionsperpage' => 0, 164 'grade' => 100.0, 165 'sumgrades' => 2, 166 'seb_requiresafeexambrowser' => $requiresafeexambrowser, 167 ]); 168 $quiz->seb_showsebdownloadlink = 1; 169 $quiz->coursemodule = $quiz->cmid; 170 171 // Create a couple of questions. 172 $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question'); 173 $cat = $questiongenerator->create_question_category(); 174 175 $saq = $questiongenerator->create_question('shortanswer', null, ['category' => $cat->id]); 176 quiz_add_quiz_question($saq->id, $quiz); 177 $numq = $questiongenerator->create_question('numerical', null, ['category' => $cat->id]); 178 quiz_add_quiz_question($numq->id, $quiz); 179 180 return $quiz; 181 } 182 183 /** 184 * Answer questions for a quiz + user. 185 * 186 * @param \stdClass $quiz Quiz to attempt. 187 * @param \stdClass $user A user to attempt the quiz. 188 * @return array 189 */ 190 protected function attempt_quiz($quiz, $user) { 191 $this->setUser($user); 192 193 $starttime = time(); 194 $quizobj = mod_quiz\quiz_settings::create($quiz->id, $user->id); 195 196 $quba = \question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context()); 197 $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour); 198 199 // Start the attempt. 200 $attempt = quiz_create_attempt($quizobj, 1, false, $starttime, false, $user->id); 201 quiz_start_new_attempt($quizobj, $quba, $attempt, 1, $starttime); 202 quiz_attempt_save_started($quizobj, $quba, $attempt); 203 204 // Answer the questions. 205 $attemptobj = quiz_attempt::create($attempt->id); 206 207 $tosubmit = [ 208 1 => ['answer' => 'frog'], 209 2 => ['answer' => '3.14'], 210 ]; 211 212 $attemptobj->process_submitted_actions($starttime, false, $tosubmit); 213 214 // Finish the attempt. 215 $attemptobj = quiz_attempt::create($attempt->id); 216 $attemptobj->process_finish($starttime, false); 217 218 $this->setUser(); 219 220 return [$quizobj, $quba, $attemptobj]; 221 } 222 223 /** 224 * Create test template. 225 * 226 * @param string|null $xml Template content. 227 * @return \quizaccess_seb\template Just created template. 228 */ 229 public function create_template(string $xml = null) { 230 $data = []; 231 232 if (!is_null($xml)) { 233 $data['content'] = $xml; 234 } 235 236 return $this->getDataGenerator()->get_plugin_generator('quizaccess_seb')->create_template($data); 237 } 238 239 /** 240 * Get access manager for testing. 241 * 242 * @return \quizaccess_seb\seb_access_manager 243 */ 244 protected function get_access_manager() { 245 return new seb_access_manager(new mod_quiz\quiz_settings($this->quiz, 246 get_coursemodule_from_id('quiz', $this->quiz->cmid), $this->course)); 247 } 248 249 /** 250 * A helper method to make the rule form the currently created quiz and course. 251 * 252 * @return access_rule_base|null 253 */ 254 protected function make_rule() { 255 return \quizaccess_seb::make( 256 new mod_quiz\quiz_settings($this->quiz, get_coursemodule_from_id('quiz', $this->quiz->cmid), $this->course), 257 0, 258 true 259 ); 260 } 261 262 /** 263 * A helper method to set up quiz view page. 264 */ 265 protected function set_up_quiz_view_page() { 266 global $PAGE; 267 268 $page = new \moodle_page(); 269 $page->set_context(\context_module::instance($this->quiz->cmid)); 270 $page->set_course($this->course); 271 $page->set_pagelayout('standard'); 272 $page->set_pagetype("mod-quiz-view"); 273 $page->set_url('/mod/quiz/view.php?id=' . $this->quiz->cmid); 274 275 $PAGE = $page; 276 } 277 278 /** 279 * Get a test object containing mock test settings. 280 * 281 * @return \stdClass Settings. 282 */ 283 protected function get_test_settings(array $settings = []) : \stdClass { 284 return (object) array_merge([ 285 'quizid' => 1, 286 'cmid' => 1, 287 'requiresafeexambrowser' => '1', 288 'showsebtaskbar' => '1', 289 'showwificontrol' => '0', 290 'showreloadbutton' => '1', 291 'showtime' => '0', 292 'showkeyboardlayout' => '1', 293 'allowuserquitseb' => '1', 294 'quitpassword' => 'test', 295 'linkquitseb' => '', 296 'userconfirmquit' => '1', 297 'enableaudiocontrol' => '1', 298 'muteonstartup' => '0', 299 'allowspellchecking' => '0', 300 'allowreloadinexam' => '1', 301 'activateurlfiltering' => '1', 302 'filterembeddedcontent' => '0', 303 'expressionsallowed' => 'test.com', 304 'regexallowed' => '', 305 'expressionsblocked' => '', 306 'regexblocked' => '', 307 'showsebdownloadlink' => '1', 308 ], $settings); 309 } 310 311 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body