Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403] [Versions 39 and 310]
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 * Glossary lib tests. 19 * 20 * @package mod_glossary 21 * @copyright 2015 Frédéric Massart - FMCorz.net 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 defined('MOODLE_INTERNAL') || die(); 26 27 global $CFG; 28 require_once($CFG->dirroot . '/mod/glossary/lib.php'); 29 require_once($CFG->dirroot . '/mod/glossary/locallib.php'); 30 31 /** 32 * Glossary lib testcase. 33 * 34 * @package mod_glossary 35 * @copyright 2015 Frédéric Massart - FMCorz.net 36 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 37 */ 38 class mod_glossary_lib_testcase extends advanced_testcase { 39 40 public function test_glossary_view() { 41 global $CFG; 42 $origcompletion = $CFG->enablecompletion; 43 $CFG->enablecompletion = true; 44 $this->resetAfterTest(true); 45 46 // Generate all the things. 47 $c1 = $this->getDataGenerator()->create_course(array('enablecompletion' => 1)); 48 $g1 = $this->getDataGenerator()->create_module('glossary', array( 49 'course' => $c1->id, 50 'completion' => COMPLETION_TRACKING_AUTOMATIC, 51 'completionview' => 1 52 )); 53 $g2 = $this->getDataGenerator()->create_module('glossary', array( 54 'course' => $c1->id, 55 'completion' => COMPLETION_TRACKING_AUTOMATIC, 56 'completionview' => 1 57 )); 58 $u1 = $this->getDataGenerator()->create_user(); 59 $this->getDataGenerator()->enrol_user($u1->id, $c1->id); 60 $modinfo = course_modinfo::instance($c1->id); 61 $cm1 = $modinfo->get_cm($g1->cmid); 62 $cm2 = $modinfo->get_cm($g2->cmid); 63 $ctx1 = $cm1->context; 64 $completion = new completion_info($c1); 65 66 $this->setUser($u1); 67 68 // Confirm what we've set up. 69 $this->assertEquals(COMPLETION_NOT_VIEWED, $completion->get_data($cm1, false, $u1->id)->viewed); 70 $this->assertEquals(COMPLETION_INCOMPLETE, $completion->get_data($cm1, false, $u1->id)->completionstate); 71 $this->assertEquals(COMPLETION_NOT_VIEWED, $completion->get_data($cm2, false, $u1->id)->viewed); 72 $this->assertEquals(COMPLETION_INCOMPLETE, $completion->get_data($cm2, false, $u1->id)->completionstate); 73 74 // Simulate the view call. 75 $sink = $this->redirectEvents(); 76 glossary_view($g1, $c1, $cm1, $ctx1, 'letter'); 77 $events = $sink->get_events(); 78 79 // Assertions. 80 $this->assertCount(3, $events); 81 $this->assertEquals('\core\event\course_module_completion_updated', $events[0]->eventname); 82 $this->assertEquals('\core\event\course_module_completion_updated', $events[1]->eventname); 83 $this->assertEquals('\mod_glossary\event\course_module_viewed', $events[2]->eventname); 84 $this->assertEquals($g1->id, $events[2]->objectid); 85 $this->assertEquals('letter', $events[2]->other['mode']); 86 $this->assertEquals(COMPLETION_VIEWED, $completion->get_data($cm1, false, $u1->id)->viewed); 87 $this->assertEquals(COMPLETION_COMPLETE, $completion->get_data($cm1, false, $u1->id)->completionstate); 88 $this->assertEquals(COMPLETION_NOT_VIEWED, $completion->get_data($cm2, false, $u1->id)->viewed); 89 $this->assertEquals(COMPLETION_INCOMPLETE, $completion->get_data($cm2, false, $u1->id)->completionstate); 90 91 // Tear down. 92 $sink->close(); 93 $CFG->enablecompletion = $origcompletion; 94 } 95 96 public function test_glossary_entry_view() { 97 $this->resetAfterTest(true); 98 99 // Generate all the things. 100 $gg = $this->getDataGenerator()->get_plugin_generator('mod_glossary'); 101 $c1 = $this->getDataGenerator()->create_course(); 102 $g1 = $this->getDataGenerator()->create_module('glossary', array('course' => $c1->id)); 103 $e1 = $gg->create_content($g1); 104 $u1 = $this->getDataGenerator()->create_user(); 105 $ctx = context_module::instance($g1->cmid); 106 $this->getDataGenerator()->enrol_user($u1->id, $c1->id); 107 108 // Assertions. 109 $sink = $this->redirectEvents(); 110 glossary_entry_view($e1, $ctx); 111 $events = $sink->get_events(); 112 $this->assertCount(1, $events); 113 $this->assertEquals('\mod_glossary\event\entry_viewed', $events[0]->eventname); 114 $this->assertEquals($e1->id, $events[0]->objectid); 115 $sink->close(); 116 } 117 118 public function test_glossary_core_calendar_provide_event_action() { 119 $this->resetAfterTest(); 120 $this->setAdminUser(); 121 122 // Create the activity. 123 $course = $this->getDataGenerator()->create_course(); 124 $glossary = $this->getDataGenerator()->create_module('glossary', array('course' => $course->id)); 125 126 // Create a calendar event. 127 $event = $this->create_action_event($course->id, $glossary->id, 128 \core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED); 129 130 // Create an action factory. 131 $factory = new \core_calendar\action_factory(); 132 133 // Decorate action event. 134 $actionevent = mod_glossary_core_calendar_provide_event_action($event, $factory); 135 136 // Confirm the event was decorated. 137 $this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent); 138 $this->assertEquals(get_string('view'), $actionevent->get_name()); 139 $this->assertInstanceOf('moodle_url', $actionevent->get_url()); 140 $this->assertEquals(1, $actionevent->get_item_count()); 141 $this->assertTrue($actionevent->is_actionable()); 142 } 143 144 public function test_glossary_core_calendar_provide_event_action_as_non_user() { 145 global $CFG; 146 147 $this->resetAfterTest(); 148 $this->setAdminUser(); 149 150 // Create the activity. 151 $course = $this->getDataGenerator()->create_course(); 152 $glossary = $this->getDataGenerator()->create_module('glossary', array('course' => $course->id)); 153 154 // Create a calendar event. 155 $event = $this->create_action_event($course->id, $glossary->id, 156 \core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED); 157 158 // Now log out. 159 $CFG->forcelogin = true; // We don't want to be logged in as guest, as guest users might still have some capabilities. 160 $this->setUser(); 161 162 // Create an action factory. 163 $factory = new \core_calendar\action_factory(); 164 165 // Decorate action event for the student. 166 $actionevent = mod_glossary_core_calendar_provide_event_action($event, $factory); 167 168 // Confirm the event is not shown at all. 169 $this->assertNull($actionevent); 170 } 171 172 public function test_glossary_core_calendar_provide_event_action_for_user() { 173 global $CFG; 174 175 $this->resetAfterTest(); 176 $this->setAdminUser(); 177 178 // Create a course. 179 $course = $this->getDataGenerator()->create_course(); 180 181 // Create a student. 182 $student = $this->getDataGenerator()->create_and_enrol($course, 'student'); 183 184 // Create the activity. 185 $glossary = $this->getDataGenerator()->create_module('glossary', array('course' => $course->id)); 186 187 // Create a calendar event. 188 $event = $this->create_action_event($course->id, $glossary->id, 189 \core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED); 190 191 // Now log out. 192 $CFG->forcelogin = true; // We don't want to be logged in as guest, as guest users might still have some capabilities. 193 $this->setUser(); 194 195 // Create an action factory. 196 $factory = new \core_calendar\action_factory(); 197 198 // Decorate action event for the student. 199 $actionevent = mod_glossary_core_calendar_provide_event_action($event, $factory, $student->id); 200 201 // Confirm the event was decorated. 202 $this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent); 203 $this->assertEquals(get_string('view'), $actionevent->get_name()); 204 $this->assertInstanceOf('moodle_url', $actionevent->get_url()); 205 $this->assertEquals(1, $actionevent->get_item_count()); 206 $this->assertTrue($actionevent->is_actionable()); 207 } 208 209 public function test_glossary_core_calendar_provide_event_action_in_hidden_section() { 210 $this->resetAfterTest(); 211 $this->setAdminUser(); 212 213 // Create a course. 214 $course = $this->getDataGenerator()->create_course(); 215 216 // Create a student. 217 $student = $this->getDataGenerator()->create_and_enrol($course, 'student'); 218 219 // Create the activity. 220 $glossary = $this->getDataGenerator()->create_module('glossary', array('course' => $course->id)); 221 222 // Create a calendar event. 223 $event = $this->create_action_event($course->id, $glossary->id, 224 \core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED); 225 226 // Set sections 0 as hidden. 227 set_section_visible($course->id, 0, 0); 228 229 // Create an action factory. 230 $factory = new \core_calendar\action_factory(); 231 232 // Decorate action event for the student. 233 $actionevent = mod_glossary_core_calendar_provide_event_action($event, $factory, $student->id); 234 235 // Confirm the event is not shown at all. 236 $this->assertNull($actionevent); 237 } 238 239 public function test_glossary_core_calendar_provide_event_action_already_completed() { 240 global $CFG; 241 242 $this->resetAfterTest(); 243 $this->setAdminUser(); 244 245 $CFG->enablecompletion = 1; 246 247 // Create the activity. 248 $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1)); 249 $glossary = $this->getDataGenerator()->create_module('glossary', array('course' => $course->id), 250 array('completion' => 2, 'completionview' => 1, 'completionexpected' => time() + DAYSECS)); 251 252 // Get some additional data. 253 $cm = get_coursemodule_from_instance('glossary', $glossary->id); 254 255 // Create a calendar event. 256 $event = $this->create_action_event($course->id, $glossary->id, 257 \core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED); 258 259 // Mark the activity as completed. 260 $completion = new completion_info($course); 261 $completion->set_module_viewed($cm); 262 263 // Create an action factory. 264 $factory = new \core_calendar\action_factory(); 265 266 // Decorate action event. 267 $actionevent = mod_glossary_core_calendar_provide_event_action($event, $factory); 268 269 // Ensure result was null. 270 $this->assertNull($actionevent); 271 } 272 273 public function test_glossary_core_calendar_provide_event_action_already_completed_for_user() { 274 global $CFG; 275 276 $this->resetAfterTest(); 277 $this->setAdminUser(); 278 279 $CFG->enablecompletion = 1; 280 281 // Create a course. 282 $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1)); 283 284 // Create a student. 285 $student = $this->getDataGenerator()->create_and_enrol($course, 'student'); 286 287 // Create the activity. 288 $glossary = $this->getDataGenerator()->create_module('glossary', array('course' => $course->id), 289 array('completion' => 2, 'completionview' => 1, 'completionexpected' => time() + DAYSECS)); 290 291 // Get some additional data. 292 $cm = get_coursemodule_from_instance('glossary', $glossary->id); 293 294 // Create a calendar event. 295 $event = $this->create_action_event($course->id, $glossary->id, 296 \core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED); 297 298 // Mark the activity as completed for the user. 299 $completion = new completion_info($course); 300 $completion->set_module_viewed($cm, $student->id); 301 302 // Create an action factory. 303 $factory = new \core_calendar\action_factory(); 304 305 // Decorate action event. 306 $actionevent = mod_glossary_core_calendar_provide_event_action($event, $factory, $student->id); 307 308 // Ensure result was null. 309 $this->assertNull($actionevent); 310 } 311 312 /** 313 * Creates an action event. 314 * 315 * @param int $courseid The course id. 316 * @param int $instanceid The instance id. 317 * @param string $eventtype The event type. 318 * @return bool|calendar_event 319 */ 320 private function create_action_event($courseid, $instanceid, $eventtype) { 321 $event = new stdClass(); 322 $event->name = 'Calendar event'; 323 $event->modulename = 'glossary'; 324 $event->courseid = $courseid; 325 $event->instance = $instanceid; 326 $event->type = CALENDAR_EVENT_TYPE_ACTION; 327 $event->eventtype = $eventtype; 328 $event->timestart = time(); 329 330 return calendar_event::create($event); 331 } 332 333 /** 334 * Test the callback responsible for returning the completion rule descriptions. 335 * This function should work given either an instance of the module (cm_info), such as when checking the active rules, 336 * or if passed a stdClass of similar structure, such as when checking the the default completion settings for a mod type. 337 */ 338 public function test_mod_glossary_completion_get_active_rule_descriptions() { 339 $this->resetAfterTest(); 340 $this->setAdminUser(); 341 342 // Two activities, both with automatic completion. One has the 'completionsubmit' rule, one doesn't. 343 $course = $this->getDataGenerator()->create_course(['enablecompletion' => 2]); 344 $glossary1 = $this->getDataGenerator()->create_module('glossary', [ 345 'course' => $course->id, 346 'completion' => 2, 347 'completionentries' => 3 348 ]); 349 $glossary2 = $this->getDataGenerator()->create_module('glossary', [ 350 'course' => $course->id, 351 'completion' => 2, 352 'completionentries' => 0 353 ]); 354 $cm1 = cm_info::create(get_coursemodule_from_instance('glossary', $glossary1->id)); 355 $cm2 = cm_info::create(get_coursemodule_from_instance('glossary', $glossary2->id)); 356 357 // Data for the stdClass input type. 358 // This type of input would occur when checking the default completion rules for an activity type, where we don't have 359 // any access to cm_info, rather the input is a stdClass containing completion and customdata attributes, just like cm_info. 360 $moddefaults = new stdClass(); 361 $moddefaults->customdata = ['customcompletionrules' => ['completionentries' => 3]]; 362 $moddefaults->completion = 2; 363 364 $activeruledescriptions = [get_string('completionentriesdesc', 'glossary', $glossary1->completionentries)]; 365 $this->assertEquals(mod_glossary_get_completion_active_rule_descriptions($cm1), $activeruledescriptions); 366 $this->assertEquals(mod_glossary_get_completion_active_rule_descriptions($cm2), []); 367 $this->assertEquals(mod_glossary_get_completion_active_rule_descriptions($moddefaults), $activeruledescriptions); 368 $this->assertEquals(mod_glossary_get_completion_active_rule_descriptions(new stdClass()), []); 369 } 370 371 public function test_mod_glossary_get_tagged_entries() { 372 global $DB; 373 374 $this->resetAfterTest(); 375 $this->setAdminUser(); 376 377 // Setup test data. 378 $glossarygenerator = $this->getDataGenerator()->get_plugin_generator('mod_glossary'); 379 $course3 = $this->getDataGenerator()->create_course(); 380 $course2 = $this->getDataGenerator()->create_course(); 381 $course1 = $this->getDataGenerator()->create_course(); 382 383 // Create and enrol a student. 384 $student = self::getDataGenerator()->create_user(); 385 $studentrole = $DB->get_record('role', array('shortname' => 'student')); 386 $this->getDataGenerator()->enrol_user($student->id, $course1->id, $studentrole->id, 'manual'); 387 $this->getDataGenerator()->enrol_user($student->id, $course2->id, $studentrole->id, 'manual'); 388 389 // Create glossaries and entries. 390 $glossary1 = $this->getDataGenerator()->create_module('glossary', array('course' => $course1->id)); 391 $glossary2 = $this->getDataGenerator()->create_module('glossary', array('course' => $course2->id)); 392 $glossary3 = $this->getDataGenerator()->create_module('glossary', array('course' => $course3->id)); 393 $entry11 = $glossarygenerator->create_content($glossary1, array('tags' => array('Cats', 'Dogs'))); 394 $entry12 = $glossarygenerator->create_content($glossary1, array('tags' => array('Cats', 'mice'))); 395 $entry13 = $glossarygenerator->create_content($glossary1, array('tags' => array('Cats'))); 396 $entry14 = $glossarygenerator->create_content($glossary1); 397 $entry15 = $glossarygenerator->create_content($glossary1, array('tags' => array('Cats'))); 398 $entry16 = $glossarygenerator->create_content($glossary1, array('tags' => array('Cats'), 'approved' => false)); 399 $entry17 = $glossarygenerator->create_content($glossary1, array('tags' => array('Cats'), 'approved' => false, 'userid' => $student->id)); 400 $entry21 = $glossarygenerator->create_content($glossary2, array('tags' => array('Cats'))); 401 $entry22 = $glossarygenerator->create_content($glossary2, array('tags' => array('Cats', 'Dogs'))); 402 $entry23 = $glossarygenerator->create_content($glossary2, array('tags' => array('mice', 'Cats'))); 403 $entry31 = $glossarygenerator->create_content($glossary3, array('tags' => array('mice', 'Cats'))); 404 405 $tag = core_tag_tag::get_by_name(0, 'Cats'); 406 407 // Admin can see everything. 408 // Get first page of tagged entries (first 5 entries). 409 $res = mod_glossary_get_tagged_entries($tag, /*$exclusivemode = */false, 410 /*$fromctx = */0, /*$ctx = */0, /*$rec = */1, /*$entry = */0); 411 $this->assertRegExp('/'.$entry11->concept.'</', $res->content); 412 $this->assertRegExp('/'.$entry12->concept.'</', $res->content); 413 $this->assertRegExp('/'.$entry13->concept.'</', $res->content); 414 $this->assertNotRegExp('/'.$entry14->concept.'</', $res->content); 415 $this->assertRegExp('/'.$entry15->concept.'</', $res->content); 416 $this->assertRegExp('/'.$entry16->concept.'</', $res->content); 417 $this->assertNotRegExp('/'.$entry17->concept.'</', $res->content); 418 $this->assertNotRegExp('/'.$entry21->concept.'</', $res->content); 419 $this->assertNotRegExp('/'.$entry22->concept.'</', $res->content); 420 $this->assertNotRegExp('/'.$entry23->concept.'</', $res->content); 421 $this->assertNotRegExp('/'.$entry31->concept.'</', $res->content); 422 $this->assertEmpty($res->prevpageurl); 423 $this->assertNotEmpty($res->nextpageurl); 424 // Get second page of tagged entries (second 5 entries). 425 $res = mod_glossary_get_tagged_entries($tag, /*$exclusivemode = */false, 426 /*$fromctx = */0, /*$ctx = */0, /*$rec = */1, /*$entry = */1); 427 $this->assertNotRegExp('/'.$entry11->concept.'</', $res->content); 428 $this->assertNotRegExp('/'.$entry12->concept.'</', $res->content); 429 $this->assertNotRegExp('/'.$entry13->concept.'</', $res->content); 430 $this->assertNotRegExp('/'.$entry14->concept.'</', $res->content); 431 $this->assertNotRegExp('/'.$entry15->concept.'</', $res->content); 432 $this->assertNotRegExp('/'.$entry16->concept.'</', $res->content); 433 $this->assertRegExp('/'.$entry17->concept.'</', $res->content); 434 $this->assertRegExp('/'.$entry21->concept.'</', $res->content); 435 $this->assertRegExp('/'.$entry22->concept.'</', $res->content); 436 $this->assertRegExp('/'.$entry23->concept.'</', $res->content); 437 $this->assertRegExp('/'.$entry31->concept.'</', $res->content); 438 $this->assertNotEmpty($res->prevpageurl); 439 $this->assertEmpty($res->nextpageurl); 440 441 $this->setUser($student); 442 core_tag_index_builder::reset_caches(); 443 444 // User can not see entries in course 3 because he is not enrolled. 445 $res = mod_glossary_get_tagged_entries($tag, /*$exclusivemode = */false, 446 /*$fromctx = */0, /*$ctx = */0, /*$rec = */1, /*$entry = */1); 447 $this->assertRegExp('/'.$entry22->concept.'/', $res->content); 448 $this->assertRegExp('/'.$entry23->concept.'/', $res->content); 449 $this->assertNotRegExp('/'.$entry31->concept.'/', $res->content); 450 451 // User can search glossary entries inside a course. 452 $coursecontext = context_course::instance($course1->id); 453 $res = mod_glossary_get_tagged_entries($tag, /*$exclusivemode = */false, 454 /*$fromctx = */0, /*$ctx = */$coursecontext->id, /*$rec = */1, /*$entry = */0); 455 $this->assertRegExp('/'.$entry11->concept.'/', $res->content); 456 $this->assertRegExp('/'.$entry12->concept.'/', $res->content); 457 $this->assertRegExp('/'.$entry13->concept.'/', $res->content); 458 $this->assertNotRegExp('/'.$entry14->concept.'/', $res->content); 459 $this->assertRegExp('/'.$entry15->concept.'/', $res->content); 460 $this->assertNotRegExp('/'.$entry21->concept.'/', $res->content); 461 $this->assertNotRegExp('/'.$entry22->concept.'/', $res->content); 462 $this->assertNotRegExp('/'.$entry23->concept.'/', $res->content); 463 $this->assertEmpty($res->nextpageurl); 464 465 // User cannot see unapproved entries unless he is an author. 466 $this->assertNotRegExp('/'.$entry16->concept.'/', $res->content); 467 $this->assertRegExp('/'.$entry17->concept.'/', $res->content); 468 } 469 470 public function test_glossary_get_entries_search() { 471 $this->resetAfterTest(); 472 $this->setAdminUser(); 473 // Turn on glossary autolinking (usedynalink). 474 set_config('glossary_linkentries', 1); 475 $glossarygenerator = $this->getDataGenerator()->get_plugin_generator('mod_glossary'); 476 $course = $this->getDataGenerator()->create_course(); 477 $glossary = $this->getDataGenerator()->create_module('glossary', array('course' => $course->id)); 478 // Note this entry is not case sensitive by default (casesensitive = 0). 479 $entry = $glossarygenerator->create_content($glossary); 480 // Check that a search for the concept return the entry. 481 $concept = $entry->concept; 482 $search = glossary_get_entries_search($concept, $course->id); 483 $this->assertCount(1, $search); 484 $foundentry = array_shift($search); 485 $this->assertEquals($foundentry->concept, $entry->concept); 486 // Now try the same search but with a lowercase term. 487 $concept = strtolower($entry->concept); 488 $search = glossary_get_entries_search($concept, $course->id); 489 $this->assertCount(1, $search); 490 $foundentry = array_shift($search); 491 $this->assertEquals($foundentry->concept, $entry->concept); 492 493 // Make an entry that is case sensitive (casesensitive = 1). 494 set_config('glossary_casesensitive', 1); 495 $entry = $glossarygenerator->create_content($glossary); 496 $concept = $entry->concept; 497 $search = glossary_get_entries_search($concept, $course->id); 498 $this->assertCount(1, $search); 499 $foundentry = array_shift($search); 500 $this->assertEquals($foundentry->concept, $entry->concept); 501 // Now try the same search but with a lowercase term. 502 $concept = strtolower($entry->concept); 503 $search = glossary_get_entries_search($concept, $course->id); 504 $this->assertCount(0, $search); 505 } 506 507 public function test_mod_glossary_can_delete_entry_users() { 508 $this->resetAfterTest(); 509 510 // Create required data. 511 $course = $this->getDataGenerator()->create_course(); 512 $student = $this->getDataGenerator()->create_and_enrol($course, 'student'); 513 $anotherstudent = $this->getDataGenerator()->create_and_enrol($course, 'student'); 514 $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher'); 515 $glossary = $this->getDataGenerator()->create_module('glossary', ['course' => $course->id]); 516 517 $gg = $this->getDataGenerator()->get_plugin_generator('mod_glossary'); 518 $this->setUser($student); 519 $entry = $gg->create_content($glossary); 520 $context = context_module::instance($glossary->cmid); 521 522 // Test student can delete. 523 $this->assertTrue(mod_glossary_can_delete_entry($entry, $glossary, $context)); 524 525 // Test teacher can delete. 526 $this->setUser($teacher); 527 $this->assertTrue(mod_glossary_can_delete_entry($entry, $glossary, $context)); 528 529 // Test admin can delete. 530 $this->setAdminUser(); 531 $this->assertTrue(mod_glossary_can_delete_entry($entry, $glossary, $context)); 532 533 // Test a different student is not able to delete. 534 $this->setUser($anotherstudent); 535 $this->assertFalse(mod_glossary_can_delete_entry($entry, $glossary, $context)); 536 537 // Test exception. 538 $this->expectExceptionMessage(get_string('nopermissiontodelentry', 'error')); 539 mod_glossary_can_delete_entry($entry, $glossary, $context, false); 540 } 541 542 public function test_mod_glossary_can_delete_entry_edit_period() { 543 global $CFG; 544 $this->resetAfterTest(); 545 546 // Create required data. 547 $course = $this->getDataGenerator()->create_course(); 548 $student = $this->getDataGenerator()->create_and_enrol($course, 'student'); 549 $glossary = $this->getDataGenerator()->create_module('glossary', ['course' => $course->id, 'editalways' => 1]); 550 551 $gg = $this->getDataGenerator()->get_plugin_generator('mod_glossary'); 552 $this->setUser($student); 553 $entry = $gg->create_content($glossary); 554 $context = context_module::instance($glossary->cmid); 555 556 // Test student can always delete when edit always is set to 1. 557 $entry->timecreated = time() - 2 * $CFG->maxeditingtime; 558 $this->assertTrue(mod_glossary_can_delete_entry($entry, $glossary, $context)); 559 560 // Test student cannot delete old entries when edit always is set to 0. 561 $glossary->editalways = 0; 562 $this->assertFalse(mod_glossary_can_delete_entry($entry, $glossary, $context)); 563 564 // Test student can delete recent entries when edit always is set to 0. 565 $entry->timecreated = time(); 566 $this->assertTrue(mod_glossary_can_delete_entry($entry, $glossary, $context)); 567 568 // Check exception. 569 $entry->timecreated = time() - 2 * $CFG->maxeditingtime; 570 $this->expectExceptionMessage(get_string('errdeltimeexpired', 'glossary')); 571 mod_glossary_can_delete_entry($entry, $glossary, $context, false); 572 } 573 574 public function test_mod_glossary_delete_entry() { 575 global $DB, $CFG; 576 $this->resetAfterTest(); 577 require_once($CFG->dirroot . '/rating/lib.php'); 578 579 // Create required data. 580 $course = $this->getDataGenerator()->create_course(); 581 $student1 = $this->getDataGenerator()->create_and_enrol($course, 'student'); 582 $student2 = $this->getDataGenerator()->create_and_enrol($course, 'student'); 583 584 $record = new stdClass(); 585 $record->course = $course->id; 586 $record->assessed = RATING_AGGREGATE_AVERAGE; 587 $scale = $this->getDataGenerator()->create_scale(['scale' => 'A,B,C,D']); 588 $record->scale = "-$scale->id"; 589 $glossary = $this->getDataGenerator()->create_module('glossary', $record); 590 $context = context_module::instance($glossary->cmid); 591 $cm = get_coursemodule_from_instance('glossary', $glossary->id); 592 593 $gg = $this->getDataGenerator()->get_plugin_generator('mod_glossary'); 594 $this->setUser($student1); 595 596 // Create entry with tags and rating. 597 $entry = $gg->create_content( 598 $glossary, 599 ['approved' => 1, 'userid' => $student1->id, 'tags' => ['Cats', 'Dogs']], 600 ['alias1', 'alias2'] 601 ); 602 603 // Rate the entry as user2. 604 $rating1 = new stdClass(); 605 $rating1->contextid = $context->id; 606 $rating1->component = 'mod_glossary'; 607 $rating1->ratingarea = 'entry'; 608 $rating1->itemid = $entry->id; 609 $rating1->rating = 1; // 1 is A. 610 $rating1->scaleid = "-$scale->id"; 611 $rating1->userid = $student2->id; 612 $rating1->timecreated = time(); 613 $rating1->timemodified = time(); 614 $rating1->id = $DB->insert_record('rating', $rating1); 615 616 $sink = $this->redirectEvents(); 617 mod_glossary_delete_entry(fullclone($entry), $glossary, $cm, $context, $course); 618 $events = $sink->get_events(); 619 $event = array_pop($events); 620 621 // Check events. 622 $this->assertEquals('\mod_glossary\event\entry_deleted', $event->eventname); 623 $this->assertEquals($entry->id, $event->objectid); 624 $sink->close(); 625 626 // No entry, no alias, no ratings, no tags. 627 $this->assertEquals(0, $DB->count_records('glossary_entries', ['id' => $entry->id])); 628 $this->assertEquals(0, $DB->count_records('glossary_alias', ['entryid' => $entry->id])); 629 $this->assertEquals(0, $DB->count_records('rating', ['component' => 'mod_glossary', 'itemid' => $entry->id])); 630 $this->assertEmpty(core_tag_tag::get_by_name(0, 'Cats')); 631 } 632 633 public function test_mod_glossary_delete_entry_imported() { 634 global $DB; 635 $this->resetAfterTest(); 636 637 // Create required data. 638 $course = $this->getDataGenerator()->create_course(); 639 $student = $this->getDataGenerator()->create_and_enrol($course, 'student'); 640 641 $glossary1 = $this->getDataGenerator()->create_module('glossary', ['course' => $course->id]); 642 $glossary2 = $this->getDataGenerator()->create_module('glossary', ['course' => $course->id]); 643 644 $context = context_module::instance($glossary2->cmid); 645 $cm = get_coursemodule_from_instance('glossary', $glossary2->id); 646 647 $gg = $this->getDataGenerator()->get_plugin_generator('mod_glossary'); 648 $this->setUser($student); 649 650 $entry1 = $gg->create_content($glossary1); 651 $entry2 = $gg->create_content( 652 $glossary2, 653 ['approved' => 1, 'userid' => $student->id, 'sourceglossaryid' => $glossary1->id, 'tags' => ['Cats', 'Dogs']] 654 ); 655 656 $sink = $this->redirectEvents(); 657 mod_glossary_delete_entry(fullclone($entry2), $glossary2, $cm, $context, $course); 658 $events = $sink->get_events(); 659 $event = array_pop($events); 660 661 // Check events. 662 $this->assertEquals('\mod_glossary\event\entry_deleted', $event->eventname); 663 $this->assertEquals($entry2->id, $event->objectid); 664 $sink->close(); 665 666 // Check source. 667 $this->assertEquals(0, $DB->get_field('glossary_entries', 'sourceglossaryid', ['id' => $entry2->id])); 668 $this->assertEquals($glossary1->id, $DB->get_field('glossary_entries', 'glossaryid', ['id' => $entry2->id])); 669 670 // Tags. 671 $this->assertEmpty(core_tag_tag::get_by_name(0, 'Cats')); 672 } 673 674 public function test_mod_glossary_can_update_entry_users() { 675 $this->resetAfterTest(); 676 677 // Create required data. 678 $course = $this->getDataGenerator()->create_course(); 679 $student = $this->getDataGenerator()->create_and_enrol($course, 'student'); 680 $anotherstudent = $this->getDataGenerator()->create_and_enrol($course, 'student'); 681 $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher'); 682 $glossary = $this->getDataGenerator()->create_module('glossary', array('course' => $course->id)); 683 684 $gg = $this->getDataGenerator()->get_plugin_generator('mod_glossary'); 685 $this->setUser($student); 686 $entry = $gg->create_content($glossary); 687 $context = context_module::instance($glossary->cmid); 688 $cm = get_coursemodule_from_instance('glossary', $glossary->id); 689 690 // Test student can update. 691 $this->assertTrue(mod_glossary_can_update_entry($entry, $glossary, $context, $cm)); 692 693 // Test teacher can update. 694 $this->setUser($teacher); 695 $this->assertTrue(mod_glossary_can_update_entry($entry, $glossary, $context, $cm)); 696 697 // Test admin can update. 698 $this->setAdminUser(); 699 $this->assertTrue(mod_glossary_can_update_entry($entry, $glossary, $context, $cm)); 700 701 // Test a different student is not able to update. 702 $this->setUser($anotherstudent); 703 $this->assertFalse(mod_glossary_can_update_entry($entry, $glossary, $context, $cm)); 704 705 // Test exception. 706 $this->expectExceptionMessage(get_string('errcannoteditothers', 'glossary')); 707 mod_glossary_can_update_entry($entry, $glossary, $context, $cm, false); 708 } 709 710 public function test_mod_glossary_can_update_entry_edit_period() { 711 global $CFG; 712 $this->resetAfterTest(); 713 714 // Create required data. 715 $course = $this->getDataGenerator()->create_course(); 716 $student = $this->getDataGenerator()->create_and_enrol($course, 'student'); 717 $glossary = $this->getDataGenerator()->create_module('glossary', array('course' => $course->id, 'editalways' => 1)); 718 719 $gg = $this->getDataGenerator()->get_plugin_generator('mod_glossary'); 720 $this->setUser($student); 721 $entry = $gg->create_content($glossary); 722 $context = context_module::instance($glossary->cmid); 723 $cm = get_coursemodule_from_instance('glossary', $glossary->id); 724 725 // Test student can always update when edit always is set to 1. 726 $entry->timecreated = time() - 2 * $CFG->maxeditingtime; 727 $this->assertTrue(mod_glossary_can_update_entry($entry, $glossary, $context, $cm)); 728 729 // Test student cannot update old entries when edit always is set to 0. 730 $glossary->editalways = 0; 731 $this->assertFalse(mod_glossary_can_update_entry($entry, $glossary, $context, $cm)); 732 733 // Test student can update recent entries when edit always is set to 0. 734 $entry->timecreated = time(); 735 $this->assertTrue(mod_glossary_can_update_entry($entry, $glossary, $context, $cm)); 736 737 // Check exception. 738 $entry->timecreated = time() - 2 * $CFG->maxeditingtime; 739 $this->expectExceptionMessage(get_string('erredittimeexpired', 'glossary')); 740 mod_glossary_can_update_entry($entry, $glossary, $context, $cm, false); 741 } 742 743 public function test_prepare_entry_for_edition() { 744 global $USER; 745 $this->resetAfterTest(true); 746 747 $course = $this->getDataGenerator()->create_course(); 748 $glossary = $this->getDataGenerator()->create_module('glossary', ['course' => $course->id]); 749 $gg = $this->getDataGenerator()->get_plugin_generator('mod_glossary'); 750 751 $this->setAdminUser(); 752 $aliases = ['alias1', 'alias2']; 753 $entry = $gg->create_content( 754 $glossary, 755 ['approved' => 1, 'userid' => $USER->id], 756 $aliases 757 ); 758 759 $cat1 = $gg->create_category($glossary, [], [$entry]); 760 $gg->create_category($glossary); 761 762 $entry = mod_glossary_prepare_entry_for_edition($entry); 763 $this->assertCount(1, $entry->categories); 764 $this->assertEquals($cat1->id, $entry->categories[0]); 765 $returnedaliases = array_values(explode("\n", trim($entry->aliases))); 766 sort($returnedaliases); 767 $this->assertEquals($aliases, $returnedaliases); 768 } 769 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body