MDL-63806 glossary: Move delete code to API function
[moodle.git] / mod / glossary / tests / lib_test.php
CommitLineData
d0d4372c
FM
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
25defined('MOODLE_INTERNAL') || die();
26
27global $CFG;
28require_once($CFG->dirroot . '/mod/glossary/lib.php');
694d2f8e 29require_once($CFG->dirroot . '/mod/glossary/locallib.php');
d0d4372c
FM
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 */
38class 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
61fce284
FM
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
6c83e659
MN
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
50f34721
SR
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
00aa8d3f
SR
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
50f34721
SR
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
6c83e659
MN
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
00aa8d3f
SR
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
6c83e659
MN
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.
e1cd93ce 318 * @return bool|calendar_event
6c83e659
MN
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
e1cd93ce 330 return calendar_event::create($event);
6c83e659 331 }
8db355c5
JD
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 }
c2118c89 370
694d2f8e
AH
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();
7b14c50b
MG
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.
694d2f8e
AH
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));
7b14c50b 399 $entry17 = $glossarygenerator->create_content($glossary1, array('tags' => array('Cats'), 'approved' => false, 'userid' => $student->id));
694d2f8e
AH
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.
7b14c50b 408 // Get first page of tagged entries (first 5 entries).
694d2f8e
AH
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);
7b14c50b 417 $this->assertNotRegExp('/'.$entry17->concept.'</', $res->content);
694d2f8e
AH
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);
7b14c50b 424 // Get second page of tagged entries (second 5 entries).
694d2f8e
AH
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);
7b14c50b 433 $this->assertRegExp('/'.$entry17->concept.'</', $res->content);
694d2f8e
AH
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
694d2f8e
AH
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
7b14c50b 465 // User cannot see unapproved entries unless he is an author.
694d2f8e 466 $this->assertNotRegExp('/'.$entry16->concept.'/', $res->content);
7b14c50b 467 $this->assertRegExp('/'.$entry17->concept.'/', $res->content);
694d2f8e 468 }
af00998f
JB
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 }
0ab3fd79
JL
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 }
d0d4372c 673}