MDL-58518 calendar: ignore events from courses user not enrolled in
[moodle.git] / calendar / tests / container_test.php
CommitLineData
5ca71c2d
CB
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 * Event container tests.
19 *
20 * @package core_calendar
21 * @copyright 2017 Cameron Ball <cameron@cameron1729.xyz>
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
25defined('MOODLE_INTERNAL') || die();
26
d7bc2c6f
MN
27global $CFG;
28
29require_once($CFG->dirroot . '/calendar/lib.php');
30
5ca71c2d
CB
31use core_calendar\local\event\entities\action_event;
32use core_calendar\local\event\entities\event;
42e76c3f 33use core_calendar\local\event\entities\event_interface;
5ca71c2d 34use core_calendar\local\event\factories\event_factory;
42e76c3f 35use core_calendar\local\event\factories\event_factory_interface;
5ca71c2d 36use core_calendar\local\event\mappers\event_mapper;
42e76c3f 37use core_calendar\local\event\mappers\event_mapper_interface;
5ca71c2d
CB
38
39/**
40 * Core container testcase.
41 *
42 * @copyright 2017 Cameron Ball <cameron@cameron1729.xyz>
43 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
44 */
45class core_calendar_container_testcase extends advanced_testcase {
88d14007 46
5ca71c2d 47 /**
88d14007 48 * Test setup.
5ca71c2d 49 */
88d14007
MN
50 public function setUp() {
51 $this->resetAfterTest();
5ca71c2d 52 $this->setAdminUser();
88d14007 53 }
5ca71c2d 54
88d14007
MN
55 /**
56 * Test getting the event factory.
57 */
58 public function test_get_event_factory() {
d10693cb 59 $factory = \core_calendar\local\event\container::get_event_factory();
5ca71c2d 60
7aedfe32 61 // Test that the container is returning the right type.
5ca71c2d 62 $this->assertInstanceOf(event_factory_interface::class, $factory);
7aedfe32 63 // Test that the container is returning the right implementation.
5ca71c2d
CB
64 $this->assertInstanceOf(event_factory::class, $factory);
65
7aedfe32 66 // Test that getting the factory a second time returns the same instance.
d10693cb 67 $factory2 = \core_calendar\local\event\container::get_event_factory();
5ca71c2d 68 $this->assertTrue($factory === $factory2);
7aedfe32 69 }
5ca71c2d 70
7aedfe32
CB
71 /**
72 * Test that the event factory correctly creates instances of events.
73 *
74 * @dataProvider get_event_factory_testcases()
75 * @param \stdClass $dbrow Row from the "database".
76 */
77 public function test_event_factory_create_instance($dbrow) {
7aedfe32 78 $legacyevent = $this->create_event($dbrow);
d10693cb 79 $factory = \core_calendar\local\event\container::get_event_factory();
7aedfe32
CB
80 $course = $this->getDataGenerator()->create_course();
81 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
82 $moduleinstance = $generator->create_instance(['course' => $course->id]);
83
84 // Set some of the fake dbrow properties to match real data in the DB
85 // this is necessary as the factory hides things that modinfo doesn't
86 // know about.
5ca71c2d 87 $dbrow->id = $legacyevent->id;
7aedfe32
CB
88 $dbrow->courseid = $course->id;
89 $dbrow->instance = $moduleinstance->id;
90 $dbrow->modulename = 'assign';
5ca71c2d
CB
91 $event = $factory->create_instance($dbrow);
92
7aedfe32 93 // Test that the factory is returning the right type.
5ca71c2d 94 $this->assertInstanceOf(event_interface::class, $event);
7aedfe32 95 // Test that the factory is returning the right implementation.
5ca71c2d
CB
96 $this->assertTrue($event instanceof event || $event instanceof action_event);
97
7aedfe32 98 // Test that the event created has the correct properties.
5ca71c2d
CB
99 $this->assertEquals($legacyevent->id, $event->get_id());
100 $this->assertEquals($dbrow->description, $event->get_description()->get_value());
101 $this->assertEquals($dbrow->format, $event->get_description()->get_format());
102 $this->assertEquals($dbrow->courseid, $event->get_course()->get_id());
103
104 if ($dbrow->groupid == 0) {
105 $this->assertNull($event->get_group());
106 } else {
107 $this->assertEquals($dbrow->groupid, $event->get_group()->get_id());
108 }
109
110 $this->assertEquals($dbrow->userid, $event->get_user()->get_id());
111 $this->assertEquals($legacyevent->id, $event->get_repeats()->get_id());
112 $this->assertEquals($dbrow->modulename, $event->get_course_module()->get('modname'));
113 $this->assertEquals($dbrow->instance, $event->get_course_module()->get('instance'));
114 $this->assertEquals($dbrow->timestart, $event->get_times()->get_start_time()->getTimestamp());
115 $this->assertEquals($dbrow->timemodified, $event->get_times()->get_modified_time()->getTimestamp());
116 $this->assertEquals($dbrow->timesort, $event->get_times()->get_sort_time()->getTimestamp());
117
118 if ($dbrow->visible == 1) {
119 $this->assertTrue($event->is_visible());
120 } else {
121 $this->assertFalse($event->is_visible());
122 }
123
124 if (!$dbrow->subscriptionid) {
125 $this->assertNull($event->get_subscription());
126 } else {
127 $this->assertEquals($event->get_subscription()->get_id());
128 }
129 }
130
7aedfe32 131 /**
0c9dc98b 132 * Test that the event factory deals with invisible modules properly as admin.
7aedfe32
CB
133 *
134 * @dataProvider get_event_factory_testcases()
135 * @param \stdClass $dbrow Row from the "database".
136 */
20592f5f 137 public function test_event_factory_when_module_visibility_is_toggled_as_admin($dbrow) {
7aedfe32 138 $legacyevent = $this->create_event($dbrow);
d10693cb 139 $factory = \core_calendar\local\event\container::get_event_factory();
7aedfe32
CB
140 $course = $this->getDataGenerator()->create_course();
141 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
142 $moduleinstance = $generator->create_instance(['course' => $course->id]);
143
0c9dc98b
MN
144 $dbrow->id = $legacyevent->id;
145 $dbrow->courseid = $course->id;
146 $dbrow->instance = $moduleinstance->id;
147 $dbrow->modulename = 'assign';
148
149 set_coursemodule_visible($moduleinstance->cmid, 0);
150
151 $event = $factory->create_instance($dbrow);
152
153 // Test that the factory is returning an event as the admin can see hidden course modules.
154 $this->assertInstanceOf(event_interface::class, $event);
155 }
156
157 /**
158 * Test that the event factory deals with invisible modules properly as a guest.
159 *
160 * @dataProvider get_event_factory_testcases()
161 * @param \stdClass $dbrow Row from the "database".
162 */
20592f5f 163 public function test_event_factory_when_module_visibility_is_toggled_as_guest($dbrow) {
0c9dc98b 164 $legacyevent = $this->create_event($dbrow);
d10693cb 165 $factory = \core_calendar\local\event\container::get_event_factory();
0c9dc98b
MN
166 $course = $this->getDataGenerator()->create_course();
167 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
168 $moduleinstance = $generator->create_instance(['course' => $course->id]);
169
170 $dbrow->id = $legacyevent->id;
7aedfe32
CB
171 $dbrow->courseid = $course->id;
172 $dbrow->instance = $moduleinstance->id;
173 $dbrow->modulename = 'assign';
174
175 set_coursemodule_visible($moduleinstance->cmid, 0);
0c9dc98b
MN
176
177 // Set to a user who can not view hidden course modules.
178 $this->setGuestUser();
179
7aedfe32 180 $event = $factory->create_instance($dbrow);
0c9dc98b
MN
181
182 // Module is invisible to guest users so this should return null.
7aedfe32
CB
183 $this->assertNull($event);
184 }
185
88d14007
MN
186 /**
187 * Test that the event factory deals with completion related events properly.
188 */
20592f5f 189 public function test_event_factory_with_completion_related_event() {
88d14007
MN
190 global $CFG;
191
192 $CFG->enablecompletion = true;
193
194 // Create the course we will be using.
195 $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1));
196
197 // Add the assignment.
198 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
199 $assign = $generator->create_instance(array('course' => $course->id), array('completion' => 1));
200
201 // Create a completion event.
202 $event = new \stdClass();
203 $event->name = 'An event';
204 $event->description = 'Event description';
205 $event->format = FORMAT_HTML;
206 $event->eventtype = \core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED;
207 $event->userid = 1;
208 $event->modulename = 'assign';
209 $event->instance = $assign->id;
210 $event->courseid = $course->id;
211 $event->groupid = 0;
212 $event->timestart = time();
213 $event->timesort = time();
214 $event->timemodified = time();
215 $event->timeduration = 0;
216 $event->subscriptionid = null;
bd01fd15 217 $event->repeatid = 0;
88d14007
MN
218 $legacyevent = $this->create_event($event);
219
220 // Update the id of the event that was created.
221 $event->id = $legacyevent->id;
222
223 // Create the factory we are going to be testing the behaviour of.
d10693cb 224 $factory = \core_calendar\local\event\container::get_event_factory();
88d14007
MN
225
226 // Check that we get the correct instance.
227 $this->assertInstanceOf(event_interface::class, $factory->create_instance($event));
228
229 // Now, disable completion.
230 $CFG->enablecompletion = false;
231
232 // The result should now be null since we have disabled completion.
233 $this->assertNull($factory->create_instance($event));
234 }
235
405f8491
RW
236 /**
237 * Test that the event factory only returns an event if the logged in user
238 * is enrolled in the course.
239 */
240 public function test_event_factory_unenrolled_user() {
241 $user = $this->getDataGenerator()->create_user();
242 // Create the course we will be using.
243 $course = $this->getDataGenerator()->create_course();
244
245 // Add the assignment.
246 $generator = $this->getDataGenerator()->get_plugin_generator('mod_lesson');
247 $lesson = $generator->create_instance(array('course' => $course->id));
248
249 // Create a user override event for the lesson.
250 $event = new \stdClass();
251 $event->name = 'An event';
252 $event->description = 'Event description';
253 $event->format = FORMAT_HTML;
254 $event->eventtype = 'close';
255 $event->userid = $user->id;
256 $event->modulename = 'lesson';
257 $event->instance = $lesson->id;
258 $event->courseid = $course->id;
259 $event->groupid = 0;
260 $event->timestart = time();
261 $event->timesort = time();
262 $event->timemodified = time();
263 $event->timeduration = 0;
264 $event->subscriptionid = null;
265 $event->repeatid = 0;
266 $legacyevent = $this->create_event($event);
267
268 // Update the id of the event that was created.
269 $event->id = $legacyevent->id;
270
271 // Set the logged in user to the one we created.
272 $this->setUser($user);
273
274 // Create the factory we are going to be testing the behaviour of.
275 $factory = \core_calendar\local\event\container::get_event_factory();
276
277 // The result should be null since the user is not enrolled in the
278 // course the event is for.
279 $this->assertNull($factory->create_instance($event));
280
281 // Now enrol the user in the course.
282 $this->getDataGenerator()->enrol_user($user->id, $course->id);
283
284 // Check that we get the correct instance.
285 $this->assertInstanceOf(event_interface::class, $factory->create_instance($event));
286 }
287
5ca71c2d
CB
288 /**
289 * Test getting the event mapper.
290 */
291 public function test_get_event_mapper() {
d10693cb 292 $mapper = \core_calendar\local\event\container::get_event_mapper();
5ca71c2d
CB
293
294 $this->assertInstanceOf(event_mapper_interface::class, $mapper);
295 $this->assertInstanceOf(event_mapper::class, $mapper);
296
d10693cb 297 $mapper2 = \core_calendar\local\event\container::get_event_mapper();
5ca71c2d
CB
298
299 $this->assertTrue($mapper === $mapper2);
300 }
301
302 /**
303 * Test cases for the get event factory test.
304 */
305 public function get_event_factory_testcases() {
306 return [
307 'Data set 1' => [
308 'dbrow' => (object)[
309 'name' => 'Test event',
310 'description' => 'Hello',
311 'format' => 1,
312 'courseid' => 1,
313 'groupid' => 0,
314 'userid' => 1,
315 'repeatid' => 0,
316 'modulename' => 'assign',
317 'instance' => 2,
318 'eventtype' => 'due',
319 'timestart' => 1486396800,
320 'timeduration' => 0,
321 'timesort' => 1486396800,
322 'visible' => 1,
323 'timemodified' => 1485793098,
324 'subscriptionid' => null
325 ]
326 ],
327
328 'Data set 2' => [
329 'dbrow' => (object)[
330 'name' => 'Test event',
331 'description' => 'Hello',
332 'format' => 1,
333 'courseid' => 1,
334 'groupid' => 1,
335 'userid' => 1,
bd01fd15 336 'repeatid' => 0,
5ca71c2d
CB
337 'modulename' => 'assign',
338 'instance' => 2,
339 'eventtype' => 'due',
340 'timestart' => 1486396800,
341 'timeduration' => 0,
342 'timesort' => 1486396800,
343 'visible' => 1,
344 'timemodified' => 1485793098,
345 'subscriptionid' => null
346 ]
347 ]
348 ];
349 }
350
351 /**
352 * Helper function to create calendar events using the old code.
353 *
354 * @param array $properties A list of calendar event properties to set
e1cd93ce 355 * @return calendar_event|bool
5ca71c2d
CB
356 */
357 protected function create_event($properties = []) {
358 $record = new \stdClass();
359 $record->name = 'event name';
360 $record->eventtype = 'global';
361 $record->timestart = time();
362 $record->timeduration = 0;
363 $record->timesort = 0;
364 $record->type = 1;
365 $record->courseid = 0;
366
367 foreach ($properties as $name => $value) {
368 $record->$name = $value;
369 }
370
e1cd93ce 371 $event = new calendar_event($record);
5ca71c2d
CB
372 return $event->create($record, false);
373 }
374}