Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.

/**
 * A test helper trait.
 *
 * @package    quizaccess_seb
 * @author     Andrew Madden <andrewmadden@catalyst-au.net>
 * @copyright  2019 Catalyst IT
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */

< use quizaccess_seb\access_manager;
> use mod_quiz\local\access_rule_base; > use mod_quiz\quiz_attempt; > use quizaccess_seb\seb_access_manager;
use quizaccess_seb\settings_provider; defined('MOODLE_INTERNAL') || die(); global $CFG; require_once($CFG->dirroot . "/mod/quiz/accessrule/seb/rule.php"); // Include plugin rule class. require_once($CFG->dirroot . "/mod/quiz/mod_form.php"); // Include plugin rule class. /** * A test helper trait. It has some common helper methods. * * @copyright 2020 Catalyst IT * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ trait quizaccess_seb_test_helper_trait { /** @var \stdClass $course Test course to contain quiz. */ protected $course; /** @var \stdClass $quiz A test quiz. */ protected $quiz; /** @var \stdClass $user A test logged-in user. */ protected $user; /** * Assign a capability to $USER * The function creates a student $USER if $USER->id is empty * * @param string $capability Capability name. * @param int $contextid Context ID. * @param int $roleid Role ID. * @return int The role id - mainly returned for creation, so calling function can reuse it. */ protected function assign_user_capability($capability, $contextid, $roleid = null) { global $USER; // Create a new student $USER if $USER doesn't exist. if (empty($USER->id)) { $user = $this->getDataGenerator()->create_user(); $this->setUser($user); } if (empty($roleid)) { $roleid = \create_role('Dummy role', 'dummyrole', 'dummy role description'); } \assign_capability($capability, CAP_ALLOW, $roleid, $contextid); \role_assign($roleid, $USER->id, $contextid); \accesslib_clear_all_caches_for_unit_testing(); return $roleid; } /** * Strip the seb_ prefix from each setting key. * * @param \stdClass $settings Object containing settings. * @return \stdClass The modified settings object. */ protected function strip_all_prefixes(\stdClass $settings) : \stdClass { $newsettings = new \stdClass(); foreach ($settings as $name => $setting) { $newname = preg_replace("/^seb_/", "", $name); $newsettings->$newname = $setting; // Add new key. } return $newsettings; } /** * Creates a file in the user draft area. * * @param string $xml * @return int The user draftarea id */ protected function create_test_draftarea_file(string $xml) : int { global $USER; $itemid = 0; $usercontext = \context_user::instance($USER->id); $filerecord = [ 'contextid' => \context_user::instance($USER->id)->id, 'component' => 'user', 'filearea' => 'draft', 'itemid' => $itemid, 'filepath' => '/', 'filename' => 'test.xml' ]; $fs = get_file_storage(); $fs->create_file_from_string($filerecord, $xml); $draftitemid = 0; file_prepare_draft_area($draftitemid, $usercontext->id, 'user', 'draft', 0); return $draftitemid; } /** * Create a file in a modules filearea. * * @param string $xml XML content of the file. * @param string $cmid Course module id. * @return int Item ID of file. */ protected function create_module_test_file(string $xml, string $cmid) : int { $itemid = 0; $fs = get_file_storage(); $filerecord = [ 'contextid' => \context_module::instance($cmid)->id, 'component' => 'quizaccess_seb', 'filearea' => 'filemanager_sebconfigfile', 'itemid' => $itemid, 'filepath' => '/', 'filename' => 'test.xml' ]; $fs->create_file_from_string($filerecord, $xml); return $itemid; } /** * Create a test quiz for the specified course. * * @param \stdClass $course * @param int $requiresafeexambrowser How to use SEB for this quiz? * @return array */ protected function create_test_quiz($course, $requiresafeexambrowser = settings_provider::USE_SEB_NO) { $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz'); $quiz = $quizgenerator->create_instance([ 'course' => $course->id, 'questionsperpage' => 0, 'grade' => 100.0, 'sumgrades' => 2, 'seb_requiresafeexambrowser' => $requiresafeexambrowser, ]); $quiz->seb_showsebdownloadlink = 1; $quiz->coursemodule = $quiz->cmid; // Create a couple of questions. $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question'); $cat = $questiongenerator->create_question_category();
< $saq = $questiongenerator->create_question('shortanswer', null, array('category' => $cat->id));
> $saq = $questiongenerator->create_question('shortanswer', null, ['category' => $cat->id]);
quiz_add_quiz_question($saq->id, $quiz);
< $numq = $questiongenerator->create_question('numerical', null, array('category' => $cat->id));
> $numq = $questiongenerator->create_question('numerical', null, ['category' => $cat->id]);
quiz_add_quiz_question($numq->id, $quiz); return $quiz; } /** * Answer questions for a quiz + user. * * @param \stdClass $quiz Quiz to attempt. * @param \stdClass $user A user to attempt the quiz. * @return array */ protected function attempt_quiz($quiz, $user) { $this->setUser($user); $starttime = time();
< $quizobj = \quiz::create($quiz->id, $user->id);
> $quizobj = mod_quiz\quiz_settings::create($quiz->id, $user->id);
$quba = \question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context()); $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour); // Start the attempt. $attempt = quiz_create_attempt($quizobj, 1, false, $starttime, false, $user->id); quiz_start_new_attempt($quizobj, $quba, $attempt, 1, $starttime); quiz_attempt_save_started($quizobj, $quba, $attempt); // Answer the questions.
< $attemptobj = \quiz_attempt::create($attempt->id);
> $attemptobj = quiz_attempt::create($attempt->id);
$tosubmit = [ 1 => ['answer' => 'frog'], 2 => ['answer' => '3.14'], ]; $attemptobj->process_submitted_actions($starttime, false, $tosubmit); // Finish the attempt.
< $attemptobj = \quiz_attempt::create($attempt->id);
> $attemptobj = quiz_attempt::create($attempt->id);
$attemptobj->process_finish($starttime, false); $this->setUser(); return [$quizobj, $quba, $attemptobj]; } /** * Create test template. * * @param string|null $xml Template content. * @return \quizaccess_seb\template Just created template. */ public function create_template(string $xml = null) { $data = []; if (!is_null($xml)) { $data['content'] = $xml; } return $this->getDataGenerator()->get_plugin_generator('quizaccess_seb')->create_template($data); } /** * Get access manager for testing. *
< * @return \quizaccess_seb\access_manager
> * @return \quizaccess_seb\seb_access_manager
*/ protected function get_access_manager() {
< return new access_manager(new \quiz($this->quiz,
> return new seb_access_manager(new mod_quiz\quiz_settings($this->quiz,
get_coursemodule_from_id('quiz', $this->quiz->cmid), $this->course)); } /** * A helper method to make the rule form the currently created quiz and course. *
< * @return \quiz_access_rule_base|null
> * @return access_rule_base|null
*/ protected function make_rule() { return \quizaccess_seb::make(
< new \quiz($this->quiz, get_coursemodule_from_id('quiz', $this->quiz->cmid), $this->course),
> new mod_quiz\quiz_settings($this->quiz, get_coursemodule_from_id('quiz', $this->quiz->cmid), $this->course),
0, true ); } /** * A helper method to set up quiz view page. */ protected function set_up_quiz_view_page() { global $PAGE; $page = new \moodle_page(); $page->set_context(\context_module::instance($this->quiz->cmid)); $page->set_course($this->course); $page->set_pagelayout('standard'); $page->set_pagetype("mod-quiz-view"); $page->set_url('/mod/quiz/view.php?id=' . $this->quiz->cmid); $PAGE = $page; } /** * Get a test object containing mock test settings. * * @return \stdClass Settings. */ protected function get_test_settings(array $settings = []) : \stdClass { return (object) array_merge([ 'quizid' => 1, 'cmid' => 1, 'requiresafeexambrowser' => '1', 'showsebtaskbar' => '1', 'showwificontrol' => '0', 'showreloadbutton' => '1', 'showtime' => '0', 'showkeyboardlayout' => '1', 'allowuserquitseb' => '1', 'quitpassword' => 'test', 'linkquitseb' => '', 'userconfirmquit' => '1', 'enableaudiocontrol' => '1', 'muteonstartup' => '0', 'allowspellchecking' => '0', 'allowreloadinexam' => '1', 'activateurlfiltering' => '1', 'filterembeddedcontent' => '0', 'expressionsallowed' => 'test.com', 'regexallowed' => '', 'expressionsblocked' => '', 'regexblocked' => '', 'showsebdownloadlink' => '1', ], $settings); } }