2cd22ea0516cab70a6e47822d75c183e81de9ec8
[moodle.git] / calendar / tests / event_factory_test.php
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/>.
17 /**
18  * Event factory test.
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  */
25 defined('MOODLE_INTERNAL') || die();
27 global $CFG;
28 require_once($CFG->dirroot . '/calendar/lib.php');
30 use core_calendar\local\event\factories\event_factory;
31 use core_calendar\local\event\entities\event_interface;
33 /**
34  * Event factory testcase.
35  *
36  * @copyright 2017 Cameron Ball <cameron@cameron1729.xyz>
37  * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
38  */
39 class core_calendar_event_factory_testcase extends advanced_testcase {
40     /**
41      * Test event class getters.
42      *
43      * @dataProvider create_instance_testcases()
44      * @param \stdClass $dbrow Row from the event table.
45      * @param callable  $actioncallbackapplier     Action callback applier.
46      * @param callable  $visibilitycallbackapplier Visibility callback applier.
47      * @param callable  $bailoutcheck              Early bail out check function.
48      * @param string    $expectedclass             Class the factory is expected to produce.
49      * @param mixed     $expectedattributevalue    Expected value of the modified attribute.
50      */
51     public function test_create_instance(
52         $dbrow,
53         callable $actioncallbackapplier,
54         callable $visibilitycallbackapplier,
55         callable $bailoutcheck,
56         $expectedclass,
57         $expectedattributevalue
58     ) {
59         $this->resetAfterTest(true);
60         $this->setAdminUser();
61         $event = $this->create_event();
62         $coursecache = [];
63         $modulecache = [];
64         $factory = new event_factory(
65             $actioncallbackapplier,
66             $visibilitycallbackapplier,
67             $bailoutcheck,
68             $coursecache,
69             $modulecache
70         );
71         $dbrow->id = $event->id;
72         $instance = $factory->create_instance($dbrow);
74         if ($expectedclass) {
75             $this->assertInstanceOf($expectedclass, $instance);
76         }
78         if (is_null($expectedclass)) {
79             $this->assertNull($instance);
80         }
82         if ($expectedattributevalue) {
83             $this->assertEquals($instance->testattribute, $expectedattributevalue);
84         }
85     }
87     /**
88      * Test invalid callback exception.
89      */
90     public function test_invalid_action_callback() {
91         $this->resetAfterTest(true);
92         $this->setAdminUser();
93         $event = $this->create_event();
94         $coursecache = [];
95         $modulecache = [];
96         $factory = new event_factory(
97             function () {
98                 return 'hello';
99             },
100             function () {
101                 return true;
102             },
103             function () {
104                 return false;
105             },
106             $coursecache,
107             $modulecache
108         );
110         $this->expectException('\core_calendar\local\event\exceptions\invalid_callback_exception');
111         $factory->create_instance(
112             (object)[
113                 'id' => $event->id,
114                 'name' => 'test',
115                 'description' => 'Test description',
116                 'format' => 2,
117                 'courseid' => 1,
118                 'groupid' => 1,
119                 'userid' => 1,
120                 'repeatid' => 0,
121                 'modulename' => 'assign',
122                 'instance' => 1,
123                 'eventtype' => 'due',
124                 'type' => CALENDAR_EVENT_TYPE_ACTION,
125                 'timestart' => 123456789,
126                 'timeduration' => 12,
127                 'timemodified' => 123456789,
128                 'timesort' => 123456789,
129                 'visible' => 1,
130                 'subscriptionid' => 1
131             ]
132         );
133     }
135     /**
136      * Test invalid callback exception.
137      */
138     public function test_invalid_visibility_callback() {
139         $this->resetAfterTest(true);
140         $this->setAdminUser();
141         $event = $this->create_event();
142         $coursecache = [];
143         $modulecache = [];
144         $factory = new event_factory(
145             function ($event) {
146                 return $event;
147             },
148             function () {
149                 return 'asdf';
150             },
151             function () {
152                 return false;
153             },
154             $coursecache,
155             $modulecache
156         );
158         $this->expectException('\core_calendar\local\event\exceptions\invalid_callback_exception');
159         $factory->create_instance(
160             (object)[
161                 'id' => $event->id,
162                 'name' => 'test',
163                 'description' => 'Test description',
164                 'format' => 2,
165                 'courseid' => 1,
166                 'groupid' => 1,
167                 'userid' => 1,
168                 'repeatid' => 0,
169                 'modulename' => 'assign',
170                 'instance' => 1,
171                 'eventtype' => 'due',
172                 'type' => CALENDAR_EVENT_TYPE_ACTION,
173                 'timestart' => 123456789,
174                 'timeduration' => 12,
175                 'timemodified' => 123456789,
176                 'timesort' => 123456789,
177                 'visible' => 1,
178                 'subscriptionid' => 1
179             ]
180         );
181     }
183     /**
184      * Test invalid callback exception.
185      */
186     public function test_invalid_bail_callback() {
187         $this->resetAfterTest(true);
188         $this->setAdminUser();
189         $event = $this->create_event();
190         $coursecache = [];
191         $modulecache = [];
192         $factory = new event_factory(
193             function ($event) {
194                 return $event;
195             },
196             function () {
197                 return true;
198             },
199             function () {
200                 return 'asdf';
201             },
202             $coursecache,
203             $modulecache
204         );
206         $this->expectException('\core_calendar\local\event\exceptions\invalid_callback_exception');
207         $factory->create_instance(
208             (object)[
209                 'id' => $event->id,
210                 'name' => 'test',
211                 'description' => 'Test description',
212                 'format' => 2,
213                 'courseid' => 1,
214                 'groupid' => 1,
215                 'userid' => 1,
216                 'repeatid' => 0,
217                 'modulename' => 'assign',
218                 'instance' => 1,
219                 'eventtype' => 'due',
220                 'type' => CALENDAR_EVENT_TYPE_ACTION,
221                 'timestart' => 123456789,
222                 'timeduration' => 12,
223                 'timemodified' => 123456789,
224                 'timesort' => 123456789,
225                 'visible' => 1,
226                 'subscriptionid' => 1
227             ]
228         );
229     }
231     /**
232      * Test the factory's course cache.
233      */
234     public function test_course_cache() {
235         $this->resetAfterTest(true);
236         $this->setAdminUser();
237         $course = self::getDataGenerator()->create_course();
238         $event = $this->create_event(['courseid' => $course->id]);
239         $coursecache = [];
240         $modulecache = [];
241         $factory = new event_factory(
242             function ($event) {
243                 return $event;
244             },
245             function () {
246                 return true;
247             },
248             function () {
249                 return false;
250             },
251             $coursecache,
252             $modulecache
253         );
255         $instance = $factory->create_instance(
256             (object)[
257                 'id' => $event->id,
258                 'name' => 'test',
259                 'description' => 'Test description',
260                 'format' => 2,
261                 'courseid' => $course->id,
262                 'groupid' => 1,
263                 'userid' => 1,
264                 'repeatid' => 0,
265                 'modulename' => 'assign',
266                 'instance' => 1,
267                 'eventtype' => 'due',
268                 'type' => CALENDAR_EVENT_TYPE_ACTION,
269                 'timestart' => 123456789,
270                 'timeduration' => 12,
271                 'timemodified' => 123456789,
272                 'timesort' => 123456789,
273                 'visible' => 1,
274                 'subscriptionid' => 1
275             ]
276         );
278         $instance->get_course()->get('fullname');
279         $this->assertArrayHasKey($course->id, $coursecache);
280     }
282     /**
283      * Test the factory's module cache.
284      */
285     public function test_module_cache() {
286         $this->resetAfterTest(true);
287         $this->setAdminUser();
288         $course = self::getDataGenerator()->create_course();
289         $event = $this->create_event(['courseid' => $course->id]);
290         $plugingenerator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
291         $assigninstance = $plugingenerator->create_instance(['course' => $course->id]);
293         $coursecache = [];
294         $modulecache = [];
295         $factory = new event_factory(
296             function ($event) {
297                 return $event;
298             },
299             function () {
300                 return true;
301             },
302             function () {
303                 return false;
304             },
305             $coursecache,
306             $modulecache
307         );
309         $instance = $factory->create_instance(
310             (object)[
311                 'id' => $event->id,
312                 'name' => 'test',
313                 'description' => 'Test description',
314                 'format' => 2,
315                 'courseid' => 0,
316                 'groupid' => 1,
317                 'userid' => 1,
318                 'repeatid' => 0,
319                 'modulename' => 'assign',
320                 'instance' => $assigninstance->id,
321                 'eventtype' => 'due',
322                 'type' => CALENDAR_EVENT_TYPE_ACTION,
323                 'timestart' => 123456789,
324                 'timeduration' => 12,
325                 'timemodified' => 123456789,
326                 'timesort' => 123456789,
327                 'visible' => 1,
328                 'subscriptionid' => 1
329             ]
330         );
332         $instance->get_course_module()->get('course');
333         $this->assertArrayHasKey('assign' . '_' . $assigninstance->id, $modulecache);
334     }
336     /**
337      * Testcases for the create instance test.
338      *
339      * @return array Array of testcases.
340      */
341     public function create_instance_testcases() {
342         return [
343             'Sample event record with event exposed' => [
344                 'dbrow' => (object)[
345                     'name' => 'Test event',
346                     'description' => 'Hello',
347                     'format' => 1,
348                     'courseid' => 1,
349                     'groupid' => 1,
350                     'userid' => 1,
351                     'repeatid' => 0,
352                     'modulename' => 'Test module',
353                     'instance' => 1,
354                     'eventtype' => 'Due',
355                     'type' => CALENDAR_EVENT_TYPE_ACTION,
356                     'timestart' => 123456789,
357                     'timeduration' => 123456789,
358                     'timemodified' => 123456789,
359                     'timesort' => 123456789,
360                     'visible' => true,
361                     'subscriptionid' => 1
362                 ],
363                 'actioncallbackapplier' => function(event_interface $event) {
364                     $event->testattribute = 'Hello';
365                     return $event;
366                 },
367                 'visibilitycallbackapplier' => function(event_interface $event) {
368                     return true;
369                 },
370                 'bailoutcheck' => function() {
371                     return false;
372                 },
373                 event_interface::class,
374                 'Hello'
375             ],
376             'Sample event record with event hidden' => [
377                 'dbrow' => (object)[
378                     'name' => 'Test event',
379                     'description' => 'Hello',
380                     'format' => 1,
381                     'courseid' => 1,
382                     'groupid' => 1,
383                     'userid' => 1,
384                     'repeatid' => 0,
385                     'modulename' => 'Test module',
386                     'instance' => 1,
387                     'eventtype' => 'Due',
388                     'type' => CALENDAR_EVENT_TYPE_ACTION,
389                     'timestart' => 123456789,
390                     'timeduration' => 123456789,
391                     'timemodified' => 123456789,
392                     'timesort' => 123456789,
393                     'visible' => true,
394                     'subscriptionid' => 1
395                 ],
396                 'actioncallbackapplier' => function(event_interface $event) {
397                     $event->testattribute = 'Hello';
398                     return $event;
399                 },
400                 'visibilitycallbackapplier' => function(event_interface $event) {
401                     return false;
402                 },
403                 'bailoutcheck' => function() {
404                     return false;
405                 },
406                 null,
407                 null
408             ],
409             'Sample event record with early bail' => [
410                 'dbrow' => (object)[
411                     'name' => 'Test event',
412                     'description' => 'Hello',
413                     'format' => 1,
414                     'courseid' => 1,
415                     'groupid' => 1,
416                     'userid' => 1,
417                     'repeatid' => 0,
418                     'modulename' => 'Test module',
419                     'instance' => 1,
420                     'eventtype' => 'Due',
421                     'type' => CALENDAR_EVENT_TYPE_ACTION,
422                     'timestart' => 123456789,
423                     'timeduration' => 123456789,
424                     'timemodified' => 123456789,
425                     'timesort' => 123456789,
426                     'visible' => true,
427                     'subscriptionid' => 1
428                 ],
429                 'actioncallbackapplier' => function(event_interface $event) {
430                     $event->testattribute = 'Hello';
431                     return $event;
432                 },
433                 'visibilitycallbackapplier' => function(event_interface $event) {
434                     return true;
435                 },
436                 'bailoutcheck' => function() {
437                     return true;
438                 },
439                 null,
440                 null
441             ]
442         ];
443     }
445     /**
446      * Helper function to create calendar events using the old code.
447      *
448      * @param array $properties A list of calendar event properties to set
449      * @return calendar_event
450      */
451     protected function create_event($properties = []) {
452         $record = new \stdClass();
453         $record->name = 'event name';
454         $record->eventtype = 'global';
455         $record->timestart = time();
456         $record->timeduration = 0;
457         $record->timesort = 0;
458         $record->type = 1;
459         $record->courseid = 0;
461         foreach ($properties as $name => $value) {
462             $record->$name = $value;
463         }
465         $event = new calendar_event($record);
466         return $event->create($record, false);
467     }