Merge branch 'MDL-81073' of https://github.com/paulholden/moodle
[moodle.git] / mod / quiz / tests / quiz_question_helper_test_trait.php
blob198c41e9968aadd478d5a7bbeb0e8c8e05bbd6f7
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.
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 use mod_quiz\quiz_attempt;
17 use mod_quiz\quiz_settings;
19 /**
20 * Helper trait for quiz question unit tests.
22 * This trait helps to execute different tests for quiz, for example if it needs to create a quiz, add question
23 * to the question, add random quetion to the quiz, do a backup or restore.
25 * @package mod_quiz
26 * @category test
27 * @copyright 2021 Catalyst IT Australia Pty Ltd
28 * @author Safat Shahin <safatshahin@catalyst-au.net>
29 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
31 trait quiz_question_helper_test_trait {
33 /** @var \stdClass $course Test course to contain quiz. */
34 protected $course;
36 /** @var \stdClass $quiz A test quiz. */
37 protected $quiz;
39 /** @var \stdClass $user A test logged-in user. */
40 protected $user;
42 /**
43 * Create a test quiz for the specified course.
45 * @param \stdClass $course
46 * @return \stdClass
48 protected function create_test_quiz(\stdClass $course): \stdClass {
50 /** @var mod_quiz_generator $quizgenerator */
51 $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz');
53 return $quizgenerator->create_instance([
54 'course' => $course->id,
55 'questionsperpage' => 0,
56 'grade' => 100.0,
57 'sumgrades' => 2,
58 ]);
61 /**
62 * Helper method to add regular questions in quiz.
64 * @param component_generator_base $questiongenerator
65 * @param \stdClass $quiz
66 * @param array $override
68 protected function add_two_regular_questions($questiongenerator, \stdClass $quiz, $override = null): void {
69 // Create a couple of questions.
70 $cat = $questiongenerator->create_question_category($override);
72 $saq = $questiongenerator->create_question('shortanswer', null, ['category' => $cat->id]);
73 // Create another version.
74 $questiongenerator->update_question($saq);
75 quiz_add_quiz_question($saq->id, $quiz);
76 $numq = $questiongenerator->create_question('numerical', null, ['category' => $cat->id]);
77 // Create two version.
78 $questiongenerator->update_question($numq);
79 $questiongenerator->update_question($numq);
80 quiz_add_quiz_question($numq->id, $quiz);
83 /**
84 * Helper method to add random question to quiz.
86 * @param component_generator_base $questiongenerator
87 * @param \stdClass $quiz
88 * @param array $override
90 protected function add_one_random_question($questiongenerator, \stdClass $quiz, $override = []): void {
91 // Create a random question.
92 $cat = $questiongenerator->create_question_category($override);
93 $questiongenerator->create_question('truefalse', null, ['category' => $cat->id]);
94 $questiongenerator->create_question('essay', null, ['category' => $cat->id]);
95 $this->add_random_questions($quiz->id, 0, $cat->id, 1);
98 /**
99 * Attempt questions for a quiz and user.
101 * @param \stdClass $quiz Quiz to attempt.
102 * @param \stdClass $user A user to attempt the quiz.
103 * @param int $attemptnumber
104 * @return array
106 protected function attempt_quiz(\stdClass $quiz, \stdClass $user, $attemptnumber = 1): array {
107 $this->setUser($user);
109 $starttime = time();
110 $quizobj = quiz_settings::create($quiz->id, $user->id);
112 $quba = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context());
113 $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour);
115 // Start the attempt.
116 $attempt = quiz_create_attempt($quizobj, $attemptnumber, null, $starttime, false, $user->id);
117 quiz_start_new_attempt($quizobj, $quba, $attempt, $attemptnumber, $starttime);
118 quiz_attempt_save_started($quizobj, $quba, $attempt);
120 // Finish the attempt.
121 $attemptobj = quiz_attempt::create($attempt->id);
122 $attemptobj->process_finish($starttime, false);
124 $this->setUser();
125 return [$quizobj, $quba, $attemptobj];
129 * A helper method to backup test quiz.
131 * @param \stdClass $quiz Quiz to attempt.
132 * @param \stdClass $user A user to attempt the quiz.
133 * @return string A backup ID ready to be restored.
135 protected function backup_quiz(\stdClass $quiz, \stdClass $user): string {
136 global $CFG;
138 // Get the necessary files to perform backup and restore.
139 require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php');
140 require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php');
142 $backupid = 'test-question-backup-restore';
144 $bc = new backup_controller(backup::TYPE_1ACTIVITY, $quiz->cmid, backup::FORMAT_MOODLE,
145 backup::INTERACTIVE_NO, backup::MODE_GENERAL, $user->id);
146 $bc->execute_plan();
148 $results = $bc->get_results();
149 $file = $results['backup_destination'];
150 $fp = get_file_packer('application/vnd.moodle.backup');
151 $filepath = $CFG->dataroot . '/temp/backup/' . $backupid;
152 $file->extract_to_pathname($fp, $filepath);
153 $bc->destroy();
155 return $backupid;
159 * A helper method to restore provided backup.
161 * @param string $backupid Backup ID to restore.
162 * @param stdClass $course
163 * @param stdClass $user
165 protected function restore_quiz(string $backupid, stdClass $course, stdClass $user): void {
166 $rc = new restore_controller($backupid, $course->id,
167 backup::INTERACTIVE_NO, backup::MODE_GENERAL, $user->id, backup::TARGET_CURRENT_ADDING);
168 $this->assertTrue($rc->execute_precheck());
169 $rc->execute_plan();
170 $rc->destroy();
174 * A helper method to emulate duplication of the quiz.
176 * @param stdClass $course
177 * @param stdClass $quiz
178 * @return \cm_info|null
180 protected function duplicate_quiz($course, $quiz): ?\cm_info {
181 return duplicate_module($course, get_fast_modinfo($course)->get_cm($quiz->cmid));
185 * Add random questions to a quiz, with a filter condition based on a category ID.
187 * @param int $quizid The quiz to add the questions to.
188 * @param int $page The page number to add the questions to.
189 * @param int $categoryid The category ID to use for the filter condition.
190 * @param int $number The number of questions to add.
191 * @return void
193 protected function add_random_questions(int $quizid, int $page, int $categoryid, int $number): void {
194 $settings = quiz_settings::create($quizid);
195 $structure = \mod_quiz\structure::create_for_quiz($settings);
196 $filtercondition = [
197 'filter' => [
198 'category' => [
199 'jointype' => \qbank_managecategories\category_condition::JOINTYPE_DEFAULT,
200 'values' => [$categoryid],
201 'filteroptions' => ['includesubcategories' => false],
205 $structure->add_random_questions($page, $number, $filtercondition);