Merge branch 'MDL-33509-master' of git://github.com/mihailges/moodle
[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                 'categoryid' => 0,
118                 'courseid' => 1,
119                 'groupid' => 1,
120                 'userid' => 1,
121                 'repeatid' => 0,
122                 'modulename' => 'assign',
123                 'instance' => 1,
124                 'eventtype' => 'due',
125                 'type' => CALENDAR_EVENT_TYPE_ACTION,
126                 'timestart' => 123456789,
127                 'timeduration' => 12,
128                 'timemodified' => 123456789,
129                 'timesort' => 123456789,
130                 'visible' => 1,
131                 'subscriptionid' => 1,
132                 'location' => 'Test location',
133             ]
134         );
135     }
137     /**
138      * Test invalid callback exception.
139      */
140     public function test_invalid_visibility_callback() {
141         $this->resetAfterTest(true);
142         $this->setAdminUser();
143         $event = $this->create_event();
144         $coursecache = [];
145         $modulecache = [];
146         $factory = new event_factory(
147             function ($event) {
148                 return $event;
149             },
150             function () {
151                 return 'asdf';
152             },
153             function () {
154                 return false;
155             },
156             $coursecache,
157             $modulecache
158         );
160         $this->expectException('\core_calendar\local\event\exceptions\invalid_callback_exception');
161         $factory->create_instance(
162             (object)[
163                 'id' => $event->id,
164                 'name' => 'test',
165                 'description' => 'Test description',
166                 'format' => 2,
167                 'categoryid' => 0,
168                 'courseid' => 1,
169                 'groupid' => 1,
170                 'userid' => 1,
171                 'repeatid' => 0,
172                 'modulename' => 'assign',
173                 'instance' => 1,
174                 'eventtype' => 'due',
175                 'type' => CALENDAR_EVENT_TYPE_ACTION,
176                 'timestart' => 123456789,
177                 'timeduration' => 12,
178                 'timemodified' => 123456789,
179                 'timesort' => 123456789,
180                 'visible' => 1,
181                 'subscriptionid' => 1,
182                 'location' => 'Test location',
183             ]
184         );
185     }
187     /**
188      * Test invalid callback exception.
189      */
190     public function test_invalid_bail_callback() {
191         $this->resetAfterTest(true);
192         $this->setAdminUser();
193         $event = $this->create_event();
194         $coursecache = [];
195         $modulecache = [];
196         $factory = new event_factory(
197             function ($event) {
198                 return $event;
199             },
200             function () {
201                 return true;
202             },
203             function () {
204                 return 'asdf';
205             },
206             $coursecache,
207             $modulecache
208         );
210         $this->expectException('\core_calendar\local\event\exceptions\invalid_callback_exception');
211         $factory->create_instance(
212             (object)[
213                 'id' => $event->id,
214                 'name' => 'test',
215                 'description' => 'Test description',
216                 'format' => 2,
217                 'categoryid' => 0,
218                 'courseid' => 1,
219                 'groupid' => 1,
220                 'userid' => 1,
221                 'repeatid' => 0,
222                 'modulename' => 'assign',
223                 'instance' => 1,
224                 'eventtype' => 'due',
225                 'type' => CALENDAR_EVENT_TYPE_ACTION,
226                 'timestart' => 123456789,
227                 'timeduration' => 12,
228                 'timemodified' => 123456789,
229                 'timesort' => 123456789,
230                 'visible' => 1,
231                 'subscriptionid' => 1,
232                 'location' => 'Test location',
233             ]
234         );
235     }
237     /**
238      * Test the factory's course cache.
239      */
240     public function test_course_cache() {
241         $this->resetAfterTest(true);
242         $this->setAdminUser();
243         $course = self::getDataGenerator()->create_course();
244         $event = $this->create_event(['courseid' => $course->id]);
245         $coursecache = [];
246         $modulecache = [];
247         $factory = new event_factory(
248             function ($event) {
249                 return $event;
250             },
251             function () {
252                 return true;
253             },
254             function () {
255                 return false;
256             },
257             $coursecache,
258             $modulecache
259         );
261         $instance = $factory->create_instance(
262             (object)[
263                 'id' => $event->id,
264                 'name' => 'test',
265                 'description' => 'Test description',
266                 'format' => 2,
267                 'categoryid' => 0,
268                 'courseid' => $course->id,
269                 'groupid' => 1,
270                 'userid' => 1,
271                 'repeatid' => 0,
272                 'modulename' => 'assign',
273                 'instance' => 1,
274                 'eventtype' => 'due',
275                 'type' => CALENDAR_EVENT_TYPE_ACTION,
276                 'timestart' => 123456789,
277                 'timeduration' => 12,
278                 'timemodified' => 123456789,
279                 'timesort' => 123456789,
280                 'visible' => 1,
281                 'subscriptionid' => 1,
282                 'location' => 'Test location',
283             ]
284         );
286         $instance->get_course()->get('fullname');
287         $this->assertArrayHasKey($course->id, $coursecache);
288     }
290     /**
291      * Test the factory's module cache.
292      */
293     public function test_module_cache() {
294         $this->resetAfterTest(true);
295         $this->setAdminUser();
296         $course = self::getDataGenerator()->create_course();
297         $event = $this->create_event(['courseid' => $course->id]);
298         $plugingenerator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
299         $assigninstance = $plugingenerator->create_instance(['course' => $course->id]);
301         $coursecache = [];
302         $modulecache = [];
303         $factory = new event_factory(
304             function ($event) {
305                 return $event;
306             },
307             function () {
308                 return true;
309             },
310             function () {
311                 return false;
312             },
313             $coursecache,
314             $modulecache
315         );
317         $instance = $factory->create_instance(
318             (object)[
319                 'id' => $event->id,
320                 'name' => 'test',
321                 'description' => 'Test description',
322                 'format' => 2,
323                 'categoryid' => 0,
324                 'courseid' => 0,
325                 'groupid' => 1,
326                 'userid' => 1,
327                 'repeatid' => 0,
328                 'modulename' => 'assign',
329                 'instance' => $assigninstance->id,
330                 'eventtype' => 'due',
331                 'type' => CALENDAR_EVENT_TYPE_ACTION,
332                 'timestart' => 123456789,
333                 'timeduration' => 12,
334                 'timemodified' => 123456789,
335                 'timesort' => 123456789,
336                 'visible' => 1,
337                 'subscriptionid' => 1,
338                 'location' => 'Test location',
339             ]
340         );
342         $instance->get_course_module()->get('course');
343         $this->assertArrayHasKey('assign' . '_' . $assigninstance->id, $modulecache);
344     }
346     /**
347      * Testcases for the create instance test.
348      *
349      * @return array Array of testcases.
350      */
351     public function create_instance_testcases() {
352         return [
353             'Sample event record with event exposed' => [
354                 'dbrow' => (object)[
355                     'name' => 'Test event',
356                     'description' => 'Hello',
357                     'format' => 1,
358                     'categoryid' => 0,
359                     'courseid' => 1,
360                     'groupid' => 1,
361                     'userid' => 1,
362                     'repeatid' => 0,
363                     'modulename' => 'Test module',
364                     'instance' => 1,
365                     'eventtype' => 'Due',
366                     'type' => CALENDAR_EVENT_TYPE_ACTION,
367                     'timestart' => 123456789,
368                     'timeduration' => 123456789,
369                     'timemodified' => 123456789,
370                     'timesort' => 123456789,
371                     'visible' => true,
372                     'subscriptionid' => 1,
373                     'location' => 'Test location',
374                 ],
375                 'actioncallbackapplier' => function(event_interface $event) {
376                     $event->testattribute = 'Hello';
377                     return $event;
378                 },
379                 'visibilitycallbackapplier' => function(event_interface $event) {
380                     return true;
381                 },
382                 'bailoutcheck' => function() {
383                     return false;
384                 },
385                 event_interface::class,
386                 'Hello'
387             ],
388             'Sample event record with event hidden' => [
389                 'dbrow' => (object)[
390                     'name' => 'Test event',
391                     'description' => 'Hello',
392                     'format' => 1,
393                     'categoryid' => 0,
394                     'courseid' => 1,
395                     'groupid' => 1,
396                     'userid' => 1,
397                     'repeatid' => 0,
398                     'modulename' => 'Test module',
399                     'instance' => 1,
400                     'eventtype' => 'Due',
401                     'type' => CALENDAR_EVENT_TYPE_ACTION,
402                     'timestart' => 123456789,
403                     'timeduration' => 123456789,
404                     'timemodified' => 123456789,
405                     'timesort' => 123456789,
406                     'visible' => true,
407                     'subscriptionid' => 1,
408                     'location' => 'Test location',
409                 ],
410                 'actioncallbackapplier' => function(event_interface $event) {
411                     $event->testattribute = 'Hello';
412                     return $event;
413                 },
414                 'visibilitycallbackapplier' => function(event_interface $event) {
415                     return false;
416                 },
417                 'bailoutcheck' => function() {
418                     return false;
419                 },
420                 null,
421                 null
422             ],
423             'Sample event record with early bail' => [
424                 'dbrow' => (object)[
425                     'name' => 'Test event',
426                     'description' => 'Hello',
427                     'format' => 1,
428                     'categoryid' => 0,
429                     'courseid' => 1,
430                     'groupid' => 1,
431                     'userid' => 1,
432                     'repeatid' => 0,
433                     'modulename' => 'Test module',
434                     'instance' => 1,
435                     'eventtype' => 'Due',
436                     'type' => CALENDAR_EVENT_TYPE_ACTION,
437                     'timestart' => 123456789,
438                     'timeduration' => 123456789,
439                     'timemodified' => 123456789,
440                     'timesort' => 123456789,
441                     'visible' => true,
442                     'subscriptionid' => 1,
443                     'location' => 'Test location',
444                 ],
445                 'actioncallbackapplier' => function(event_interface $event) {
446                     $event->testattribute = 'Hello';
447                     return $event;
448                 },
449                 'visibilitycallbackapplier' => function(event_interface $event) {
450                     return true;
451                 },
452                 'bailoutcheck' => function() {
453                     return true;
454                 },
455                 null,
456                 null
457             ]
458         ];
459     }
461     /**
462      * Helper function to create calendar events using the old code.
463      *
464      * @param array $properties A list of calendar event properties to set
465      * @return calendar_event
466      */
467     protected function create_event($properties = []) {
468         $record = new \stdClass();
469         $record->name = 'event name';
470         $record->eventtype = 'global';
471         $record->timestart = time();
472         $record->timeduration = 0;
473         $record->timesort = 0;
474         $record->type = 1;
475         $record->courseid = 0;
476         $record->categoryid = 0;
478         foreach ($properties as $name => $value) {
479             $record->$name = $value;
480         }
482         $event = new calendar_event($record);
483         return $event->create($record, false);
484     }