See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 401 and 402] [Versions 401 and 403]
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 mod_quiz\question\bank\qbank_helper; 20 21 /** 22 * Class mod_quiz_local_structure_slot_random_test 23 * Class for tests related to the {@link \mod_quiz\local\structure\slot_random} class. 24 * 25 * @package mod_quiz 26 * @category test 27 * @copyright 2018 Shamim Rezaie <shamim@moodle.com> 28 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 29 */ 30 class local_structure_slot_random_test extends \advanced_testcase { 31 /** 32 * Constructor test. 33 */ 34 public function test_constructor() { 35 global $SITE; 36 37 $this->resetAfterTest(); 38 $this->setAdminUser(); 39 40 // Create a quiz. 41 $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz'); 42 $quiz = $quizgenerator->create_instance(array('course' => $SITE->id, 'questionsperpage' => 3, 'grade' => 100.0)); 43 44 // Create a question category in the system context. 45 $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question'); 46 $category = $questiongenerator->create_question_category(); 47 48 // Create a random question without adding it to a quiz. 49 // We don't want to use quiz_add_random_questions because that itself, instantiates an object from the slot_random class. 50 $form = new \stdClass(); 51 $form->category = $category->id . ',' . $category->contextid; 52 $form->includesubcategories = true; 53 $form->fromtags = []; 54 $form->defaultmark = 1; 55 $form->status = \core_question\local\bank\question_version_status::QUESTION_STATUS_HIDDEN; 56 $form->stamp = make_unique_id_code(); 57 58 // Set the filter conditions. 59 $filtercondition = new \stdClass(); 60 $filtercondition->questioncategoryid = $category->id; 61 $filtercondition->includingsubcategories = 1; 62 63 // Slot data. 64 $randomslotdata = new \stdClass(); 65 $randomslotdata->quizid = $quiz->id; 66 $randomslotdata->maxmark = 1; 67 $randomslotdata->usingcontextid = \context_module::instance($quiz->cmid)->id; 68 $randomslotdata->questionscontextid = $category->contextid; 69 70 // Insert the random question to the quiz. 71 $randomslot = new \mod_quiz\local\structure\slot_random($randomslotdata); 72 $randomslot->set_filter_condition($filtercondition); 73 74 $rc = new \ReflectionClass('\mod_quiz\local\structure\slot_random'); 75 $rcp = $rc->getProperty('filtercondition'); 76 $rcp->setAccessible(true); 77 $record = json_decode($rcp->getValue($randomslot)); 78 79 $this->assertEquals($quiz->id, $randomslot->get_quiz()->id); 80 $this->assertEquals($category->id, $record->questioncategoryid); 81 $this->assertEquals(1, $record->includingsubcategories); 82 83 $rcp = $rc->getProperty('record'); 84 $rcp->setAccessible(true); 85 $record = $rcp->getValue($randomslot); 86 $this->assertEquals(1, $record->maxmark); 87 } 88 89 public function test_get_quiz_quiz() { 90 global $SITE, $DB; 91 92 $this->resetAfterTest(); 93 $this->setAdminUser(); 94 95 // Create a quiz. 96 $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz'); 97 $quiz = $quizgenerator->create_instance(array('course' => $SITE->id, 'questionsperpage' => 3, 'grade' => 100.0)); 98 99 // Create a question category in the system context. 100 $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question'); 101 $category = $questiongenerator->create_question_category(); 102 103 quiz_add_random_questions($quiz, 0, $category->id, 1, false); 104 105 // Set the filter conditions. 106 $filtercondition = new \stdClass(); 107 $filtercondition->questioncategoryid = $category->id; 108 $filtercondition->includingsubcategories = 1; 109 110 // Slot data. 111 $randomslotdata = new \stdClass(); 112 $randomslotdata->quizid = $quiz->id; 113 $randomslotdata->maxmark = 1; 114 $randomslotdata->usingcontextid = \context_module::instance($quiz->cmid)->id; 115 $randomslotdata->questionscontextid = $category->contextid; 116 117 $randomslot = new \mod_quiz\local\structure\slot_random($randomslotdata); 118 $randomslot->set_filter_condition($filtercondition); 119 120 // The create_instance had injected an additional cmid propery to the quiz. Let's remove that. 121 unset($quiz->cmid); 122 123 $this->assertEquals($quiz, $randomslot->get_quiz()); 124 } 125 126 public function test_set_quiz() { 127 global $SITE, $DB; 128 129 $this->resetAfterTest(); 130 $this->setAdminUser(); 131 132 // Create a quiz. 133 $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz'); 134 $quiz = $quizgenerator->create_instance(array('course' => $SITE->id, 'questionsperpage' => 3, 'grade' => 100.0)); 135 136 // Create a question category in the system context. 137 $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question'); 138 $category = $questiongenerator->create_question_category(); 139 140 quiz_add_random_questions($quiz, 0, $category->id, 1, false); 141 142 // Set the filter conditions. 143 $filtercondition = new \stdClass(); 144 $filtercondition->questioncategoryid = $category->id; 145 $filtercondition->includingsubcategories = 1; 146 147 // Slot data. 148 $randomslotdata = new \stdClass(); 149 $randomslotdata->quizid = $quiz->id; 150 $randomslotdata->maxmark = 1; 151 $randomslotdata->usingcontextid = \context_module::instance($quiz->cmid)->id; 152 $randomslotdata->questionscontextid = $category->contextid; 153 154 $randomslot = new \mod_quiz\local\structure\slot_random($randomslotdata); 155 $randomslot->set_filter_condition($filtercondition); 156 157 // The create_instance had injected an additional cmid propery to the quiz. Let's remove that. 158 unset($quiz->cmid); 159 160 $randomslot->set_quiz($quiz); 161 162 $rc = new \ReflectionClass('\mod_quiz\local\structure\slot_random'); 163 $rcp = $rc->getProperty('quiz'); 164 $rcp->setAccessible(true); 165 $quizpropery = $rcp->getValue($randomslot); 166 167 $this->assertEquals($quiz, $quizpropery); 168 } 169 170 private function setup_for_test_tags($tagnames) { 171 global $SITE, $DB; 172 173 // Create a quiz. 174 $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz'); 175 $quiz = $quizgenerator->create_instance(array('course' => $SITE->id, 'questionsperpage' => 3, 'grade' => 100.0)); 176 177 // Create a question category in the system context. 178 $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question'); 179 $category = $questiongenerator->create_question_category(); 180 181 quiz_add_random_questions($quiz, 0, $category->id, 1, false); 182 183 // Slot data. 184 $randomslotdata = new \stdClass(); 185 $randomslotdata->quizid = $quiz->id; 186 $randomslotdata->maxmark = 1; 187 $randomslotdata->usingcontextid = \context_module::instance($quiz->cmid)->id; 188 $randomslotdata->questionscontextid = $category->contextid; 189 190 $randomslot = new \mod_quiz\local\structure\slot_random($randomslotdata); 191 192 // Create tags. 193 foreach ($tagnames as $tagname) { 194 $tagrecord = array( 195 'isstandard' => 1, 196 'flag' => 0, 197 'rawname' => $tagname, 198 'description' => $tagname . ' desc' 199 ); 200 $tags[$tagname] = $this->getDataGenerator()->create_tag($tagrecord); 201 } 202 203 return array($randomslot, $tags); 204 } 205 206 public function test_set_tags() { 207 $this->resetAfterTest(); 208 $this->setAdminUser(); 209 210 list($randomslot, $tags) = $this->setup_for_test_tags(['foo', 'bar']); 211 $filtercondition = new \stdClass(); 212 $randomslot->set_tags([$tags['foo'], $tags['bar']]); 213 $randomslot->set_filter_condition($filtercondition); 214 215 $rc = new \ReflectionClass('\mod_quiz\local\structure\slot_random'); 216 $rcp = $rc->getProperty('filtercondition'); 217 $rcp->setAccessible(true); 218 $tagspropery = $rcp->getValue($randomslot); 219 220 $this->assertEquals([ 221 $tags['foo']->id => $tags['foo'], 222 $tags['bar']->id => $tags['bar'], 223 ], (array)json_decode($tagspropery)->tags); 224 } 225 226 public function test_set_tags_twice() { 227 $this->resetAfterTest(); 228 $this->setAdminUser(); 229 230 list($randomslot, $tags) = $this->setup_for_test_tags(['foo', 'bar', 'baz']); 231 232 // Set tags for the first time. 233 $filtercondition = new \stdClass(); 234 $randomslot->set_tags([$tags['foo'], $tags['bar']]); 235 // Now set the tags again. 236 $randomslot->set_tags([$tags['baz']]); 237 $randomslot->set_filter_condition($filtercondition); 238 239 $rc = new \ReflectionClass('\mod_quiz\local\structure\slot_random'); 240 $rcp = $rc->getProperty('filtercondition'); 241 $rcp->setAccessible(true); 242 $tagspropery = $rcp->getValue($randomslot); 243 244 $this->assertEquals([ 245 $tags['baz']->id => $tags['baz'], 246 ], (array)json_decode($tagspropery)->tags); 247 } 248 249 public function test_set_tags_duplicates() { 250 $this->resetAfterTest(); 251 $this->setAdminUser(); 252 253 list($randomslot, $tags) = $this->setup_for_test_tags(['foo', 'bar', 'baz']); 254 $filtercondition = new \stdClass(); 255 $randomslot->set_tags([$tags['foo'], $tags['bar'], $tags['foo']]); 256 $randomslot->set_filter_condition($filtercondition); 257 258 $rc = new \ReflectionClass('\mod_quiz\local\structure\slot_random'); 259 $rcp = $rc->getProperty('filtercondition'); 260 $rcp->setAccessible(true); 261 $tagspropery = $rcp->getValue($randomslot); 262 263 $this->assertEquals([ 264 $tags['foo']->id => $tags['foo'], 265 $tags['bar']->id => $tags['bar'], 266 ], (array)json_decode($tagspropery)->tags); 267 } 268 269 public function test_set_tags_by_id() { 270 $this->resetAfterTest(); 271 $this->setAdminUser(); 272 273 list($randomslot, $tags) = $this->setup_for_test_tags(['foo', 'bar', 'baz']); 274 $filtercondition = new \stdClass(); 275 $randomslot->set_tags_by_id([$tags['foo']->id, $tags['bar']->id]); 276 $randomslot->set_filter_condition($filtercondition); 277 278 $rc = new \ReflectionClass('\mod_quiz\local\structure\slot_random'); 279 $rcp = $rc->getProperty('tags'); 280 $rcp->setAccessible(true); 281 $tagspropery = $rcp->getValue($randomslot); 282 283 // The set_tags_by_id function only retrieves id and name fields of the tag object. 284 $this->assertCount(2, $tagspropery); 285 $this->assertArrayHasKey($tags['foo']->id, $tagspropery); 286 $this->assertArrayHasKey($tags['bar']->id, $tagspropery); 287 $this->assertEquals( 288 (object)['id' => $tags['foo']->id, 'name' => $tags['foo']->name], 289 $tagspropery[$tags['foo']->id]->to_object() 290 ); 291 $this->assertEquals( 292 (object)['id' => $tags['bar']->id, 'name' => $tags['bar']->name], 293 $tagspropery[$tags['bar']->id]->to_object() 294 ); 295 } 296 297 public function test_set_tags_by_id_twice() { 298 $this->resetAfterTest(); 299 $this->setAdminUser(); 300 301 list($randomslot, $tags) = $this->setup_for_test_tags(['foo', 'bar', 'baz']); 302 303 // Set tags for the first time. 304 $randomslot->set_tags_by_id([$tags['foo']->id, $tags['bar']->id]); 305 // Now set the tags again. 306 $randomslot->set_tags_by_id([$tags['baz']->id]); 307 308 $rc = new \ReflectionClass('\mod_quiz\local\structure\slot_random'); 309 $rcp = $rc->getProperty('tags'); 310 $rcp->setAccessible(true); 311 $tagspropery = $rcp->getValue($randomslot); 312 313 // The set_tags_by_id function only retrieves id and name fields of the tag object. 314 $this->assertCount(1, $tagspropery); 315 $this->assertArrayHasKey($tags['baz']->id, $tagspropery); 316 $this->assertEquals( 317 (object)['id' => $tags['baz']->id, 'name' => $tags['baz']->name], 318 $tagspropery[$tags['baz']->id]->to_object() 319 ); 320 } 321 322 public function test_set_tags_by_id_duplicates() { 323 $this->resetAfterTest(); 324 $this->setAdminUser(); 325 326 list($randomslot, $tags) = $this->setup_for_test_tags(['foo', 'bar', 'baz']); 327 328 $randomslot->set_tags_by_id([$tags['foo']->id, $tags['bar']->id], $tags['foo']->id); 329 330 $rc = new \ReflectionClass('\mod_quiz\local\structure\slot_random'); 331 $rcp = $rc->getProperty('tags'); 332 $rcp->setAccessible(true); 333 $tagspropery = $rcp->getValue($randomslot); 334 335 // The set_tags_by_id function only retrieves id and name fields of the tag object. 336 $this->assertCount(2, $tagspropery); 337 $this->assertArrayHasKey($tags['foo']->id, $tagspropery); 338 $this->assertArrayHasKey($tags['bar']->id, $tagspropery); 339 $this->assertEquals( 340 (object)['id' => $tags['foo']->id, 'name' => $tags['foo']->name], 341 $tagspropery[$tags['foo']->id]->to_object() 342 ); 343 $this->assertEquals( 344 (object)['id' => $tags['bar']->id, 'name' => $tags['bar']->name], 345 $tagspropery[$tags['bar']->id]->to_object() 346 ); 347 } 348 349 public function test_insert() { 350 global $SITE; 351 352 $this->resetAfterTest(); 353 $this->setAdminUser(); 354 355 // Create a quiz. 356 $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz'); 357 $quiz = $quizgenerator->create_instance(array('course' => $SITE->id, 'questionsperpage' => 3, 'grade' => 100.0)); 358 $quizcontext = \context_module::instance($quiz->cmid); 359 360 // Create a question category in the system context. 361 $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question'); 362 $category = $questiongenerator->create_question_category(); 363 364 // Create a random question without adding it to a quiz. 365 $form = new \stdClass(); 366 $form->category = $category->id . ',' . $category->contextid; 367 $form->includesubcategories = true; 368 $form->fromtags = []; 369 $form->defaultmark = 1; 370 $form->status = \core_question\local\bank\question_version_status::QUESTION_STATUS_HIDDEN; 371 $form->stamp = make_unique_id_code(); 372 373 // Prepare 2 tags. 374 $tagrecord = array( 375 'isstandard' => 1, 376 'flag' => 0, 377 'rawname' => 'foo', 378 'description' => 'foo desc' 379 ); 380 $footag = $this->getDataGenerator()->create_tag($tagrecord); 381 $tagrecord = array( 382 'isstandard' => 1, 383 'flag' => 0, 384 'rawname' => 'bar', 385 'description' => 'bar desc' 386 ); 387 $bartag = $this->getDataGenerator()->create_tag($tagrecord); 388 389 390 // Set the filter conditions. 391 $filtercondition = new \stdClass(); 392 $filtercondition->questioncategoryid = $category->id; 393 $filtercondition->includingsubcategories = 1; 394 395 // Slot data. 396 $randomslotdata = new \stdClass(); 397 $randomslotdata->quizid = $quiz->id; 398 $randomslotdata->maxmark = 1; 399 $randomslotdata->usingcontextid = $quizcontext->id; 400 $randomslotdata->questionscontextid = $category->contextid; 401 402 // Insert the random question to the quiz. 403 $randomslot = new \mod_quiz\local\structure\slot_random($randomslotdata); 404 $randomslot->set_tags([$footag, $bartag]); 405 $randomslot->set_filter_condition($filtercondition); 406 $randomslot->insert(1); // Put the question on the first page of the quiz. 407 408 $slots = qbank_helper::get_question_structure($quiz->id, $quizcontext); 409 $quizslot = reset($slots); 410 411 $this->assertEquals($category->id, $quizslot->category); 412 $this->assertEquals(1, $quizslot->randomrecurse); 413 $this->assertEquals(1, $quizslot->maxmark); 414 $tagspropery = $quizslot->randomtags; 415 416 $this->assertCount(2, $tagspropery); 417 $this->assertEqualsCanonicalizing( 418 [ 419 ['tagid' => $footag->id, 'tagname' => $footag->name], 420 ['tagid' => $bartag->id, 'tagname' => $bartag->name] 421 ], 422 array_map(function($slottag) { 423 return ['tagid' => $slottag->id, 'tagname' => $slottag->name]; 424 }, $tagspropery)); 425 } 426 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body