Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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 core_calendar;
18
 
19
use core_calendar\local\event\entities\action_event;
20
use core_calendar\local\event\entities\event;
21
use core_calendar\local\event\entities\event_interface;
22
use core_calendar\local\event\factories\event_factory;
23
use core_calendar\local\event\factories\event_factory_interface;
24
use core_calendar\local\event\mappers\event_mapper;
25
use core_calendar\local\event\mappers\event_mapper_interface;
26
use core_completion\api;
27
 
28
defined('MOODLE_INTERNAL') || die();
29
 
30
global $CFG;
31
 
32
require_once($CFG->dirroot . '/calendar/lib.php');
33
 
34
/**
35
 * Event container test..
36
 *
37
 * @package core_calendar
38
 * @copyright 2017 Cameron Ball <cameron@cameron1729.xyz>
39
 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
40
 */
41
class container_test extends \advanced_testcase {
42
 
43
    /**
44
     * Test setup.
45
     */
46
    public function setUp(): void {
47
        $this->resetAfterTest();
48
        $this->setAdminUser();
49
    }
50
 
51
    /**
52
     * Test getting the event factory.
53
     */
11 efrain 54
    public function test_get_event_factory(): void {
1 efrain 55
        $factory = \core_calendar\local\event\container::get_event_factory();
56
 
57
        // Test that the container is returning the right type.
58
        $this->assertInstanceOf(event_factory_interface::class, $factory);
59
        // Test that the container is returning the right implementation.
60
        $this->assertInstanceOf(event_factory::class, $factory);
61
 
62
        // Test that getting the factory a second time returns the same instance.
63
        $factory2 = \core_calendar\local\event\container::get_event_factory();
64
        $this->assertTrue($factory === $factory2);
65
    }
66
 
67
    /**
68
     * Test that the event factory correctly creates instances of events.
69
     *
70
     * @dataProvider get_event_factory_testcases()
71
     * @param \stdClass $dbrow Row from the "database".
72
     */
11 efrain 73
    public function test_event_factory_create_instance($dbrow): void {
1 efrain 74
        $legacyevent = $this->create_event($dbrow);
75
        $factory = \core_calendar\local\event\container::get_event_factory();
76
        $course = $this->getDataGenerator()->create_course();
77
        $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
78
        $moduleinstance = $generator->create_instance(['course' => $course->id]);
79
 
80
        // Set some of the fake dbrow properties to match real data in the DB
81
        // this is necessary as the factory hides things that modinfo doesn't
82
        // know about.
83
        $dbrow->id = $legacyevent->id;
84
        $dbrow->courseid = $course->id;
85
        $dbrow->instance = $moduleinstance->id;
86
        $dbrow->modulename = 'assign';
87
        $event = $factory->create_instance($dbrow);
88
 
89
        // Test that the factory is returning the right type.
90
        $this->assertInstanceOf(event_interface::class, $event);
91
        // Test that the factory is returning the right implementation.
92
        $this->assertTrue($event instanceof event || $event instanceof action_event);
93
 
94
        // Test that the event created has the correct properties.
95
        $this->assertEquals($legacyevent->id, $event->get_id());
96
        $this->assertEquals($dbrow->description, $event->get_description()->get_value());
97
        $this->assertEquals($dbrow->format, $event->get_description()->get_format());
98
        $this->assertEquals($dbrow->courseid, $event->get_course()->get('id'));
99
        $this->assertEquals($dbrow->location, $event->get_location());
100
 
101
        if ($dbrow->groupid == 0) {
102
            $this->assertNull($event->get_group());
103
        } else {
104
            $this->assertEquals($dbrow->groupid, $event->get_group()->get('id'));
105
        }
106
 
107
        $this->assertEquals($dbrow->userid, $event->get_user()->get('id'));
108
        $this->assertEquals(null, $event->get_repeats());
109
        $this->assertEquals($dbrow->modulename, $event->get_course_module()->get('modname'));
110
        $this->assertEquals($dbrow->instance, $event->get_course_module()->get('instance'));
111
        $this->assertEquals($dbrow->timestart, $event->get_times()->get_start_time()->getTimestamp());
112
        $this->assertEquals($dbrow->timemodified, $event->get_times()->get_modified_time()->getTimestamp());
113
        $this->assertEquals($dbrow->timesort, $event->get_times()->get_sort_time()->getTimestamp());
114
 
115
        if ($dbrow->visible == 1) {
116
            $this->assertTrue($event->is_visible());
117
        } else {
118
            $this->assertFalse($event->is_visible());
119
        }
120
 
121
        if (!$dbrow->subscriptionid) {
122
            $this->assertNull($event->get_subscription());
123
        } else {
124
            $this->assertEquals($event->get_subscription()->get('id'));
125
        }
126
    }
127
 
128
    /**
129
     * Test that the event factory deals with invisible modules properly as admin.
130
     *
131
     * @dataProvider get_event_factory_testcases()
132
     * @param \stdClass $dbrow Row from the "database".
133
     */
11 efrain 134
    public function test_event_factory_when_module_visibility_is_toggled_as_admin($dbrow): void {
1 efrain 135
        $legacyevent = $this->create_event($dbrow);
136
        $factory = \core_calendar\local\event\container::get_event_factory();
137
        $course = $this->getDataGenerator()->create_course();
138
        $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
139
        $moduleinstance = $generator->create_instance(['course' => $course->id]);
140
 
141
        $dbrow->id = $legacyevent->id;
142
        $dbrow->courseid = $course->id;
143
        $dbrow->instance = $moduleinstance->id;
144
        $dbrow->modulename = 'assign';
145
 
146
        set_coursemodule_visible($moduleinstance->cmid, 0);
147
 
148
        $event = $factory->create_instance($dbrow);
149
 
150
        // Test that the factory is returning an event as the admin can see hidden course modules.
151
        $this->assertInstanceOf(event_interface::class, $event);
152
    }
153
 
154
    /**
155
     * Test that the event factory deals with invisible modules properly as a guest.
156
     *
157
     * @dataProvider get_event_factory_testcases()
158
     * @param \stdClass $dbrow Row from the "database".
159
     */
11 efrain 160
    public function test_event_factory_when_module_visibility_is_toggled_as_guest($dbrow): void {
1 efrain 161
        $legacyevent = $this->create_event($dbrow);
162
        $factory = \core_calendar\local\event\container::get_event_factory();
163
        $course = $this->getDataGenerator()->create_course();
164
        $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
165
        $moduleinstance = $generator->create_instance(['course' => $course->id]);
166
 
167
        $dbrow->id = $legacyevent->id;
168
        $dbrow->courseid = $course->id;
169
        $dbrow->instance = $moduleinstance->id;
170
        $dbrow->modulename = 'assign';
171
 
172
        set_coursemodule_visible($moduleinstance->cmid, 0);
173
 
174
        // Set to a user who can not view hidden course modules.
175
        $this->setGuestUser();
176
 
177
        $event = $factory->create_instance($dbrow);
178
 
179
        // Module is invisible to guest users so this should return null.
180
        $this->assertNull($event);
181
    }
182
 
183
    /**
184
     * Test that the event factory deals with invisible courses as an admin.
185
     *
186
     * @dataProvider get_event_factory_testcases()
187
     * @param \stdClass $dbrow Row from the "database".
188
     */
11 efrain 189
    public function test_event_factory_when_course_visibility_is_toggled_as_admin($dbrow): void {
1 efrain 190
        $legacyevent = $this->create_event($dbrow);
191
        $factory = \core_calendar\local\event\container::get_event_factory();
192
 
193
        // Create a hidden course with an assignment.
194
        $course = $this->getDataGenerator()->create_course(['visible' => 0]);
195
        $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
196
        $moduleinstance = $generator->create_instance(['course' => $course->id]);
197
 
198
        $dbrow->id = $legacyevent->id;
199
        $dbrow->courseid = $course->id;
200
        $dbrow->instance = $moduleinstance->id;
201
        $dbrow->modulename = 'assign';
202
        $event = $factory->create_instance($dbrow);
203
 
204
        // Module is still visible to admins even if the course is invisible.
205
        $this->assertInstanceOf(event_interface::class, $event);
206
    }
207
 
208
    /**
209
     * Test that the event factory deals with invisible courses as a student.
210
     *
211
     * @dataProvider get_event_factory_testcases()
212
     * @param \stdClass $dbrow Row from the "database".
213
     */
11 efrain 214
    public function test_event_factory_when_course_visibility_is_toggled_as_student($dbrow): void {
1 efrain 215
        $legacyevent = $this->create_event($dbrow);
216
        $factory = \core_calendar\local\event\container::get_event_factory();
217
 
218
        // Create a hidden course with an assignment.
219
        $course = $this->getDataGenerator()->create_course(['visible' => 0]);
220
        $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
221
        $moduleinstance = $generator->create_instance(['course' => $course->id]);
222
 
223
        // Enrol a student into this course.
224
        $student = $this->getDataGenerator()->create_user();
225
        $this->getDataGenerator()->enrol_user($student->id, $course->id);
226
 
227
        // Set the user to the student.
228
        $this->setUser($student);
229
 
230
        $dbrow->id = $legacyevent->id;
231
        $dbrow->courseid = $course->id;
232
        $dbrow->instance = $moduleinstance->id;
233
        $dbrow->modulename = 'assign';
234
        $event = $factory->create_instance($dbrow);
235
 
236
        // Module is invisible to students if the course is invisible.
237
        $this->assertNull($event);
238
    }
239
 
240
    /**
241
     * Test that the event factory deals with invisible categorys as an admin.
242
     */
11 efrain 243
    public function test_event_factory_when_category_visibility_is_toggled_as_admin(): void {
1 efrain 244
        // Create a hidden category.
245
        $category = $this->getDataGenerator()->create_category(['visible' => 0]);
246
 
247
        $eventdata = [
248
                'categoryid' => $category->id,
249
                'eventtype' => 'category',
250
            ];
251
        $legacyevent = $this->create_event($eventdata);
252
 
253
        $dbrow = $this->get_dbrow_from_skeleton((object) $eventdata);
254
        $dbrow->id = $legacyevent->id;
255
 
256
        $factory = \core_calendar\local\event\container::get_event_factory();
257
        $event = $factory->create_instance($dbrow);
258
 
259
        // Module is still visible to admins even if the category is invisible.
260
        $this->assertInstanceOf(event_interface::class, $event);
261
    }
262
 
263
    /**
264
     * Test that the event factory deals with invisible categorys as an user.
265
     */
11 efrain 266
    public function test_event_factory_when_category_visibility_is_toggled_as_user(): void {
1 efrain 267
        // Create a hidden category.
268
        $category = $this->getDataGenerator()->create_category(['visible' => 0]);
269
 
270
        $eventdata = [
271
                'categoryid' => $category->id,
272
                'eventtype' => 'category',
273
            ];
274
        $legacyevent = $this->create_event($eventdata);
275
 
276
        $dbrow = $this->get_dbrow_from_skeleton((object) $eventdata);
277
        $dbrow->id = $legacyevent->id;
278
 
279
        // Use a standard user.
280
        $user = $this->getDataGenerator()->create_user();
281
 
282
        // Set the user to the student.
283
        $this->setUser($user);
284
 
285
        $factory = \core_calendar\local\event\container::get_event_factory();
286
        $event = $factory->create_instance($dbrow);
287
 
288
        // Module is invisible to non-privileged users.
289
        $this->assertNull($event);
290
    }
291
 
292
    /**
293
     * Test that the event factory deals with invisible categorys as an guest.
294
     */
11 efrain 295
    public function test_event_factory_when_category_visibility_is_toggled_as_guest(): void {
1 efrain 296
        // Create a hidden category.
297
        $category = $this->getDataGenerator()->create_category(['visible' => 0]);
298
 
299
        $eventdata = [
300
                'categoryid' => $category->id,
301
                'eventtype' => 'category',
302
            ];
303
        $legacyevent = $this->create_event($eventdata);
304
 
305
        $dbrow = $this->get_dbrow_from_skeleton((object) $eventdata);
306
        $dbrow->id = $legacyevent->id;
307
 
308
        // Set the user to the student.
309
        $this->setGuestUser();
310
 
311
        $factory = \core_calendar\local\event\container::get_event_factory();
312
        $event = $factory->create_instance($dbrow);
313
 
314
        // Module is invisible to guests.
315
        $this->assertNull($event);
316
    }
317
 
318
    /**
319
     * Test that the event factory deals with completion related events properly.
320
     */
11 efrain 321
    public function test_event_factory_with_completion_related_event(): void {
1 efrain 322
        global $CFG;
323
 
324
        $CFG->enablecompletion = true;
325
 
326
        // Create the course we will be using.
327
        $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1));
328
 
329
        // Add the assignment.
330
        $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
331
        $assign = $generator->create_instance(array('course' => $course->id), array('completion' => 1));
332
 
333
        // Create a completion event.
334
        $event = new \stdClass();
335
        $event->name = 'An event';
336
        $event->description = 'Event description';
337
        $event->location = 'Event location';
338
        $event->format = FORMAT_HTML;
339
        $event->eventtype = \core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED;
340
        $event->userid = 1;
341
        $event->modulename = 'assign';
342
        $event->instance = $assign->id;
343
        $event->categoryid = 0;
344
        $event->courseid = $course->id;
345
        $event->groupid = 0;
346
        $event->timestart = time();
347
        $event->timesort = time();
348
        $event->timemodified = time();
349
        $event->timeduration = 0;
350
        $event->subscriptionid = null;
351
        $event->repeatid = 0;
352
        $legacyevent = $this->create_event($event);
353
 
354
        // Update the id of the event that was created.
355
        $event->id = $legacyevent->id;
356
 
357
        // Create the factory we are going to be testing the behaviour of.
358
        $factory = \core_calendar\local\event\container::get_event_factory();
359
 
360
        // Check that we get the correct instance.
361
        $this->assertInstanceOf(event_interface::class, $factory->create_instance($event));
362
 
363
        // Now, disable completion.
364
        $CFG->enablecompletion = false;
365
 
366
        // The result should now be null since we have disabled completion.
367
        $this->assertNull($factory->create_instance($event));
368
    }
369
 
370
    /**
371
     * Checks that completed activities events do not show.
372
     * @covers \core_calendar\local\event::init
373
     */
11 efrain 374
    public function test_event_factory_with_completed_module_related_event(): void {
1 efrain 375
        global $CFG, $DB;
376
 
377
        $this->setAdminUser();
378
 
379
        // Create a course.
380
        $course = $this->getDataGenerator()->create_course(['enablecompletion' => 1]);
381
        $user = $this->getDataGenerator()->create_and_enrol($course);
382
        // Create an assign activity with a time set.
383
        $time = time();
384
        $assign = $this->getDataGenerator()->create_module(
385
            'assign', ['course' => $course->id, 'completion' => COMPLETION_TRACKING_MANUAL]);
386
 
387
        // Create the event but set it to tomorrow.
388
        $CFG->enablecompletion = true;
389
        api::update_completion_date_event($assign->cmid, 'assign', $assign,
390
            $time + DAYSECS);
391
 
392
        $this->setUser($user);
393
        // Check that we get should be completed event.
394
        $this->assertCount(1, \core_calendar\local\event\container::get_event_vault()->get_events());
395
        // Then Complete the activity.
396
        $completion = new \completion_info($course);
397
        $cmassign = get_coursemodule_from_id('assign', $assign->cmid);
398
        // This should trigger another call to the update_completion_date_event.
399
        $completion->update_state($cmassign, COMPLETION_COMPLETE, $user->id);
400
        // Check that we do not see the event anymore.
401
        $this->assertCount(0, \core_calendar\local\event\container::get_event_vault()->get_events());
402
    }
403
 
404
 
405
    /**
406
     * Test that the event factory only returns an event if the logged in user
407
     * is enrolled in the course.
408
     */
11 efrain 409
    public function test_event_factory_unenrolled_user(): void {
1 efrain 410
        $user = $this->getDataGenerator()->create_user();
411
        // Create the course we will be using.
412
        $course = $this->getDataGenerator()->create_course();
413
 
414
        // Add the assignment.
415
        $generator = $this->getDataGenerator()->get_plugin_generator('mod_lesson');
416
        $lesson = $generator->create_instance(array('course' => $course->id));
417
 
418
        // Create a user override event for the lesson.
419
        $event = new \stdClass();
420
        $event->name = 'An event';
421
        $event->description = 'Event description';
422
        $event->location = 'Event location';
423
        $event->format = FORMAT_HTML;
424
        $event->eventtype = 'close';
425
        $event->userid = $user->id;
426
        $event->modulename = 'lesson';
427
        $event->instance = $lesson->id;
428
        $event->categoryid = 0;
429
        $event->courseid = $course->id;
430
        $event->groupid = 0;
431
        $event->timestart = time();
432
        $event->timesort = time();
433
        $event->timemodified = time();
434
        $event->timeduration = 0;
435
        $event->subscriptionid = null;
436
        $event->repeatid = 0;
437
        $legacyevent = $this->create_event($event);
438
 
439
        // Update the id of the event that was created.
440
        $event->id = $legacyevent->id;
441
 
442
        // Set the logged in user to the one we created.
443
        $this->setUser($user);
444
 
445
        // Create the factory we are going to be testing the behaviour of.
446
        $factory = \core_calendar\local\event\container::get_event_factory();
447
 
448
        // The result should be null since the user is not enrolled in the
449
        // course the event is for.
450
        $this->assertNull($factory->create_instance($event));
451
 
452
        // Now enrol the user in the course.
453
        $this->getDataGenerator()->enrol_user($user->id, $course->id);
454
 
455
        // Check that we get the correct instance.
456
        $this->assertInstanceOf(event_interface::class, $factory->create_instance($event));
457
    }
458
 
459
    /**
460
     * Test that when course module is deleted all events are also deleted.
461
     */
11 efrain 462
    public function test_delete_module_delete_events(): void {
1 efrain 463
        global $DB;
464
        $user = $this->getDataGenerator()->create_user();
465
        // Create the course we will be using.
466
        $course = $this->getDataGenerator()->create_course();
467
        $group = $this->getDataGenerator()->create_group(['courseid' => $course->id]);
468
 
469
        foreach (\core_component::get_plugin_list('mod') as $modname => $unused) {
470
            try {
471
                $generator = $this->getDataGenerator()->get_plugin_generator('mod_'.$modname);
472
            } catch (\coding_exception $e) {
473
                // Module generator is not implemented.
474
                continue;
475
            }
476
            $module = $generator->create_instance(['course' => $course->id]);
477
 
478
            // Create bunch of events of different type (user override, group override, module event).
479
            $this->create_event(['userid' => $user->id, 'modulename' => $modname, 'instance' => $module->id]);
480
            $this->create_event(['groupid' => $group->id, 'modulename' => $modname, 'instance' => $module->id]);
481
            $this->create_event(['modulename' => $modname, 'instance' => $module->id]);
482
            $this->create_event(['modulename' => $modname, 'instance' => $module->id, 'courseid' => $course->id]);
483
 
484
            // Delete module and make sure all events are deleted.
485
            course_delete_module($module->cmid);
486
            $this->assertEmpty($DB->get_record('event', ['modulename' => $modname, 'instance' => $module->id]));
487
        }
488
    }
489
 
490
    /**
491
     * Test getting the event mapper.
492
     */
11 efrain 493
    public function test_get_event_mapper(): void {
1 efrain 494
        $mapper = \core_calendar\local\event\container::get_event_mapper();
495
 
496
        $this->assertInstanceOf(event_mapper_interface::class, $mapper);
497
        $this->assertInstanceOf(event_mapper::class, $mapper);
498
 
499
        $mapper2 = \core_calendar\local\event\container::get_event_mapper();
500
 
501
        $this->assertTrue($mapper === $mapper2);
502
    }
503
 
504
    /**
505
     * Test cases for the get event factory test.
506
     */
507
    public function get_event_factory_testcases() {
508
        return [
509
            'Data set 1' => [
510
                'dbrow' => (object)[
511
                    'name' => 'Test event',
512
                    'description' => 'Hello',
513
                    'format' => 1,
514
                    'categoryid' => 0,
515
                    'courseid' => 1,
516
                    'groupid' => 0,
517
                    'userid' => 1,
518
                    'repeatid' => 0,
519
                    'modulename' => 'assign',
520
                    'instance' => 2,
521
                    'eventtype' => 'due',
522
                    'timestart' => 1486396800,
523
                    'timeduration' => 0,
524
                    'timesort' => 1486396800,
525
                    'visible' => 1,
526
                    'timemodified' => 1485793098,
527
                    'subscriptionid' => null,
528
                    'location' => 'Test location',
529
                ]
530
            ],
531
 
532
            'Data set 2' => [
533
                'dbrow' => (object)[
534
                    'name' => 'Test event',
535
                    'description' => 'Hello',
536
                    'format' => 1,
537
                    'categoryid' => 0,
538
                    'courseid' => 1,
539
                    'groupid' => 1,
540
                    'userid' => 1,
541
                    'repeatid' => 0,
542
                    'modulename' => 'assign',
543
                    'instance' => 2,
544
                    'eventtype' => 'due',
545
                    'timestart' => 1486396800,
546
                    'timeduration' => 0,
547
                    'timesort' => 1486396800,
548
                    'visible' => 1,
549
                    'timemodified' => 1485793098,
550
                    'subscriptionid' => null,
551
                    'location' => 'Test location',
552
                ]
553
            ]
554
        ];
555
    }
556
 
557
    /**
558
     * Helper function to create calendar events using the old code.
559
     *
560
     * @param array $properties A list of calendar event properties to set
561
     * @return calendar_event|bool
562
     */
563
    protected function create_event($properties = []) {
564
        $record = new \stdClass();
565
        $record->name = 'event name';
566
        $record->eventtype = 'site';
567
        $record->timestart = time();
568
        $record->timeduration = 0;
569
        $record->timesort = 0;
570
        $record->type = 1;
571
        $record->courseid = 0;
572
        $record->categoryid = 0;
573
 
574
        foreach ($properties as $name => $value) {
575
            $record->$name = $value;
576
        }
577
 
578
        $event = new \calendar_event($record);
579
        return $event->create($record, false);
580
    }
581
 
582
    /**
583
     * Pad out a basic DB row with basic information.
584
     *
585
     * @param   \stdClass   $skeleton the current skeleton
586
     * @return  \stdClass
587
     */
588
    protected function get_dbrow_from_skeleton($skeleton) {
589
        $dbrow = (object) [
590
            'name' => 'Name',
591
            'description' => 'Description',
592
            'format' => 1,
593
            'categoryid' => 0,
594
            'courseid' => 0,
595
            'groupid' => 0,
596
            'userid' => 0,
597
            'repeatid' => 0,
598
            'modulename' => '',
599
            'instance' => 0,
600
            'eventtype' => 'user',
601
            'timestart' => 1486396800,
602
            'timeduration' => 0,
603
            'timesort' => 1486396800,
604
            'visible' => 1,
605
            'timemodified' => 1485793098,
606
            'subscriptionid' => null,
607
            'location' => 'Test location',
608
        ];
609
 
610
        foreach ((array) $skeleton as $key => $value) {
611
            $dbrow->$key = $value;
612
        }
613
 
614
        return $dbrow;
615
    }
616
}