Rev 1 | Ir a la última revisión | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |
<?php// This file is part of Moodle - http://moodle.org///// Moodle is free software: you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// Moodle is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with Moodle. If not, see <http://www.gnu.org/licenses/>.namespace core_calendar;use core_calendar_external;use externallib_advanced_testcase;use core_external\external_api;defined('MOODLE_INTERNAL') || die();global $CFG;require_once($CFG->dirroot . '/webservice/tests/helpers.php');/*** External course functions unit tests** @package core_calendar* @category external* @copyright 2012 Ankit Agarwal* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later* @since Moodle 2.5*/class externallib_test extends externallib_advanced_testcase {/*** Tests set up*/protected function setUp(): void {global $CFG;require_once($CFG->dirroot . '/calendar/externallib.php');}/** Create calendar events or update them* Set $prop->id, if you want to do an update instead of creating an new event** @param string $name Event title* @param int $userid User id* @param string $type Event type* @param int $repeats Number of repeated events to create* @param int $timestart Time stamp of the event start* @param mixed $prop List of event properties as array or object* @return mixed Event object or false;* @since Moodle 2.5*/public static function create_calendar_event($name, $userid = 0, $type = 'user', $repeats = 0, $timestart = null, $prop = null) {global $CFG, $DB, $SITE;require_once("$CFG->dirroot/calendar/lib.php");if (!empty($prop)) {if (is_array($prop)) {$prop = (object)$prop;}} else {$prop = new \stdClass();}$prop->name = $name;if (empty($prop->eventtype)) {$prop->eventtype = $type;}if (empty($prop->repeats)) {$prop->repeats = $repeats;}if (empty($prop->timestart)) {$prop->timestart = time();}if (empty($prop->timeduration)) {$prop->timeduration = 0;}if (empty($prop->timesort)) {$prop->timesort = 0;}if (empty($prop->type)) {$prop->type = CALENDAR_EVENT_TYPE_STANDARD;}if (empty($prop->repeats)) {$prop->repeat = 0;} else {$prop->repeat = 1;}if (empty($prop->userid)) {if (!empty($userid)) {$prop->userid = $userid;} else {$prop->userid = 0;}}if (!isset($prop->courseid)) {// Set a default value of the event's course ID field.if ($type === 'user') {// If it's a user event, course ID should be zero.$prop->courseid = 0;} else {// Otherwise, default to the site ID.$prop->courseid = $SITE->id;}}// Determine event priority.if ($prop->courseid == 0 && isset($prop->groupid) && $prop->groupid == 0 && !empty($prop->userid)) {// User override event.$prop->priority = CALENDAR_EVENT_USER_OVERRIDE_PRIORITY;} else if ($prop->courseid != $SITE->id && !empty($prop->groupid)) {// Group override event.$priorityparams = ['courseid' => $prop->courseid, 'groupid' => $prop->groupid];// Group override event with the highest priority.$groupevents = $DB->get_records('event', $priorityparams, 'priority DESC', 'id, priority', 0, 1);$priority = 1;if (!empty($groupevents)) {$event = reset($groupevents);if (!empty($event->priority)) {$priority = $event->priority + 1;}}$prop->priority = $priority;}$event = new \calendar_event($prop);return $event->create($prop);}public function test_create_calendar_events(): void {global $DB, $USER;$this->setAdminUser();$this->resetAfterTest();$prevcount = count($DB->get_records("event"));// Create a few events and do asserts.$this->create_calendar_event('test', $USER->id);$where = $DB->sql_compare_text('name') ." = ?";$count = count($DB->get_records_select("event", $where, array('test')));$this->assertEquals(1, $count);$aftercount = count($DB->get_records("event"));$this->assertEquals($prevcount + 1, $aftercount);$this->create_calendar_event('user', $USER->id, 'user', 3);$where = $DB->sql_compare_text('name') ." = ?";$count = count($DB->get_records_select("event", $where, array('user')));$this->assertEquals(3, $count);$aftercount = count($DB->get_records("event"));$this->assertEquals($prevcount + 4, $aftercount);}/*** Test delete_calendar_events*/public function test_delete_calendar_events(): void {global $DB, $USER;$this->resetAfterTest(true);$this->setAdminUser();// Create a few stuff to test with.$user = $this->getDataGenerator()->create_user();$course = $this->getDataGenerator()->create_course();$record = new \stdClass();$record->courseid = $course->id;$group = $this->getDataGenerator()->create_group($record);$notdeletedcount = $DB->count_records('event');// Let's create a few events.$siteevent = $this->create_calendar_event('site', $USER->id, 'site');$record = new \stdClass();$record->courseid = $course->id;$courseevent = $this->create_calendar_event('course', $USER->id, 'course', 2, time(), $record);$userevent = $this->create_calendar_event('user', $USER->id);$record = new \stdClass();$record->courseid = $course->id;$record->groupid = $group->id;$groupevent = $this->create_calendar_event('group', $USER->id, 'group', 0, time(), $record);// Now lets try to delete stuff with proper rights.$events = array(array('eventid' => $siteevent->id, 'repeat' => 0),array('eventid' => $courseevent->id, 'repeat' => 1),array('eventid' => $userevent->id, 'repeat' => 0),array('eventid' => $groupevent->id, 'repeat' => 0));core_calendar_external::delete_calendar_events($events);// Check to see if things were deleted properly.$deletedcount = $DB->count_records('event');$this->assertEquals($notdeletedcount, $deletedcount);// Let's create a few events.$siteevent = $this->create_calendar_event('site', $USER->id, 'site');$record = new \stdClass();$record->courseid = $course->id;$courseevent = $this->create_calendar_event('course', $USER->id, 'course', 3, time(), $record);$userevent = $this->create_calendar_event('user', $user->id);$record = new \stdClass();$record->courseid = $course->id;$record->groupid = $group->id;$groupevent = $this->create_calendar_event('group', $USER->id, 'group', 0, time(), $record);$this->setuser($user);$sitecontext = \context_system::instance();$coursecontext = \context_course::instance($course->id);$usercontext = \context_user::instance($user->id);$role = $DB->get_record('role', array('shortname' => 'student'));$this->getDataGenerator()->enrol_user($user->id, $course->id, $role->id);// Remove all caps.$this->unassignUserCapability('moodle/calendar:manageentries', $sitecontext->id, $role->id);$this->unassignUserCapability('moodle/calendar:manageentries', $coursecontext->id, $role->id);$this->unassignUserCapability('moodle/calendar:managegroupentries', $coursecontext->id, $role->id);$this->unassignUserCapability('moodle/calendar:manageownentries', $usercontext->id, $role->id);// Assign proper caps and attempt delete.$this->assignUserCapability('moodle/calendar:manageentries', $sitecontext->id, $role->id);$events = array(array('eventid' => $siteevent->id, 'repeat' => 0),);core_calendar_external::delete_calendar_events($events);$deletedcount = $DB->count_records('event');$count = $notdeletedcount+5;$this->assertEquals($count, $deletedcount);$this->assignUserCapability('moodle/calendar:manageentries', $sitecontext->id, $role->id);$events = array(array('eventid' => $courseevent->id, 'repeat' => 0),);core_calendar_external::delete_calendar_events($events);$deletedcount = $DB->count_records('event');$count = $notdeletedcount+4;$this->assertEquals($count, $deletedcount);$this->assignUserCapability('moodle/calendar:manageownentries', $usercontext->id, $role->id);$events = array(array('eventid' => $userevent->id, 'repeat' => 0),);core_calendar_external::delete_calendar_events($events);$deletedcount = $DB->count_records('event');$count = $notdeletedcount+3;$this->assertEquals($count, $deletedcount);$this->assignUserCapability('moodle/calendar:managegroupentries', $coursecontext->id, $role->id);$events = array(array('eventid' => $groupevent->id, 'repeat' => 0),);core_calendar_external::delete_calendar_events($events);$deletedcount = $DB->count_records('event');$count = $notdeletedcount+2;$this->assertEquals($count, $deletedcount);$notdeletedcount = $deletedcount;// Let us try deleting without caps.$siteevent = $this->create_calendar_event('site', $USER->id, 'site');$record = new \stdClass();$record->courseid = $course->id;$courseevent = $this->create_calendar_event('course', $USER->id, 'course', 3, time(), $record);$userevent = $this->create_calendar_event('user', $USER->id);$record = new \stdClass();$record->courseid = $course->id;$record->groupid = $group->id;$groupevent = $this->create_calendar_event('group', $USER->id, 'group', 0, time(), $record);$this->setGuestUser();$events = array(array('eventid' => $siteevent->id, 'repeat' => 0),array('eventid' => $courseevent->id, 'repeat' => 0),array('eventid' => $userevent->id, 'repeat' => 0),array('eventid' => $groupevent->id, 'repeat' => 0));$this->expectException(\moodle_exception::class);core_calendar_external::delete_calendar_events($events);}/*** Test get_calendar_events*/public function test_get_calendar_events(): void {global $DB, $USER;$this->resetAfterTest(true);set_config('calendar_adminseesall', 1);$this->setAdminUser();// Create a few stuff to test with.$user = $this->getDataGenerator()->create_user();$user2 = $this->getDataGenerator()->create_user();$course = $this->getDataGenerator()->create_course();$category = $this->getDataGenerator()->create_category();$category2 = $this->getDataGenerator()->create_category();$category2b = $this->getDataGenerator()->create_category(['parent' => $category2->id]);$course3 = $this->getDataGenerator()->create_course(['category' => $category2b->id]);$role = $DB->get_record('role', array('shortname' => 'student'));$this->getDataGenerator()->enrol_user($user2->id, $course3->id, $role->id);$record = new \stdClass();$record->courseid = $course->id;$group = $this->getDataGenerator()->create_group($record);$beforecount = $DB->count_records('event');// Let's create a few events.$siteevent = $this->create_calendar_event('site', $USER->id, 'site');// This event will have description with an inline fake image.$draftidfile = file_get_unused_draft_itemid();$usercontext = \context_course::instance($course->id);$filerecord = array('contextid' => $usercontext->id,'component' => 'user','filearea' => 'draft','itemid' => $draftidfile,'filepath' => '/','filename' => 'fakeimage.png',);$fs = get_file_storage();$fs->create_file_from_string($filerecord, 'img contents');$record = new \stdClass();$record->courseid = $course->id;$record->groupid = 0;$record->description = array('format' => FORMAT_HTML,'text' => 'Text with img <img src="@@PLUGINFILE@@/fakeimage.png">','itemid' => $draftidfile);$courseevent = $this->create_calendar_event('course', $USER->id, 'course', 2, time(), $record);$record = new \stdClass();$record->courseid = 0;$record->groupid = 0;$userevent = $this->create_calendar_event('user', $USER->id, 'user', 0, time(), $record);$record = new \stdClass();$record->courseid = $course->id;$record->groupid = $group->id;$groupevent = $this->create_calendar_event('group', $USER->id, 'group', 0, time(), $record);$paramevents = array ('eventids' => array($siteevent->id), 'courseids' => array($course->id),'groupids' => array($group->id), 'categoryids' => array($category->id));$options = array ('siteevents' => true, 'userevents' => true);$events = core_calendar_external::get_calendar_events($paramevents, $options);$events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);// Check to see if we got all events.$this->assertEquals(5, count($events['events']));$this->assertEquals(0, count($events['warnings']));$options = array ('siteevents' => true, 'userevents' => true, 'timeend' => time() + 7*WEEKSECS);$events = core_calendar_external::get_calendar_events($paramevents, $options);$events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);$this->assertEquals(5, count($events['events']));$this->assertEquals(0, count($events['warnings']));// Expect the same URL in the description of two different events (because they are repeated).$coursecontext = \context_course::instance($course->id);$expectedurl = "webservice/pluginfile.php/$coursecontext->id/calendar/event_description/$courseevent->id/fakeimage.png";$withdescription = 0;foreach ($events['events'] as $event) {if (!empty($event['description'])) {$withdescription++;$this->assertStringContainsString($expectedurl, $event['description']);}}$this->assertEquals(2, $withdescription);// Let's play around with caps.// Create user event for the user $user.$record = new \stdClass();$record->courseid = 0;$record->groupid = 0;$this->create_calendar_event('user', $user->id, 'user', 0, time(), $record);$this->setUser($user);$events = core_calendar_external::get_calendar_events($paramevents, $options);$events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);$this->assertEquals(2, count($events['events'])); // site, user.$this->assertEquals(2, count($events['warnings'])); // course, group.$role = $DB->get_record('role', array('shortname' => 'student'));$this->getDataGenerator()->enrol_user($user->id, $course->id, $role->id);$events = core_calendar_external::get_calendar_events($paramevents, $options);$events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);$this->assertEquals(4, count($events['events'])); // site, user, both course events.$this->assertEquals(1, count($events['warnings'])); // group.$options = array ('siteevents' => true, 'userevents' => true, 'timeend' => time() + HOURSECS);$events = core_calendar_external::get_calendar_events($paramevents, $options);$events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);$this->assertEquals(3, count($events['events'])); // site, user, one course event.$this->assertEquals(1, count($events['warnings'])); // group.groups_add_member($group, $user);$events = core_calendar_external::get_calendar_events($paramevents, $options);$events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);$this->assertEquals(4, count($events['events'])); // site, user, group, one course event.$this->assertEquals(0, count($events['warnings']));$paramevents = array ('courseids' => array($course->id), 'groupids' => array($group->id));$events = core_calendar_external::get_calendar_events($paramevents, $options);$events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);$this->assertEquals(4, count($events['events'])); // site, user, group, one course event.$this->assertEquals(0, count($events['warnings']));$paramevents = array ('groupids' => array($group->id, 23));$events = core_calendar_external::get_calendar_events($paramevents, $options);$events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);$this->assertEquals(3, count($events['events'])); // site, user, group.$this->assertEquals(1, count($events['warnings']));$paramevents = array ('courseids' => array(23));$events = core_calendar_external::get_calendar_events($paramevents, $options);$events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);$this->assertEquals(2, count($events['events'])); // site, user.$this->assertEquals(1, count($events['warnings']));$paramevents = array ();$options = array ('siteevents' => false, 'userevents' => false, 'timeend' => time() + 7*WEEKSECS);$events = core_calendar_external::get_calendar_events($paramevents, $options);$events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);$this->assertEquals(0, count($events['events'])); // nothing returned.$this->assertEquals(0, count($events['warnings']));$paramevents = array ('eventids' => array($siteevent->id, $groupevent->id));$options = array ('siteevents' => false, 'userevents' => false, 'timeend' => time() + 7*WEEKSECS);$events = core_calendar_external::get_calendar_events($paramevents, $options);$events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);$this->assertEquals(2, count($events['events'])); // site, group.$this->assertEquals(0, count($events['warnings']));$paramevents = array ('eventids' => array($siteevent->id));$events = core_calendar_external::get_calendar_events($paramevents, $options);$events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);$this->assertEquals(1, count($events['events'])); // site.$this->assertEquals(0, count($events['warnings']));// Try getting a course event by its id.$paramevents = array ('eventids' => array($courseevent->id));$events = core_calendar_external::get_calendar_events($paramevents, $options);$events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);$this->assertEquals(1, count($events['events']));$this->assertEquals(0, count($events['warnings']));// Now, create an activity event.$this->setAdminUser();$nexttime = time() + DAYSECS;$assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id, 'duedate' => $nexttime));$this->setUser($user);$paramevents = array ('courseids' => array($course->id));$options = array ('siteevents' => true, 'userevents' => true, 'timeend' => time() + WEEKSECS);$events = core_calendar_external::get_calendar_events($paramevents, $options);$events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);$this->assertCount(5, $events['events']);// Hide the assignment.set_coursemodule_visible($assign->cmid, 0);// Empty all the caches that may be affected by this change.accesslib_clear_all_caches_for_unit_testing();\course_modinfo::clear_instance_cache();$events = core_calendar_external::get_calendar_events($paramevents, $options);$events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);// Expect one less.$this->assertCount(4, $events['events']);// Create some category events.$this->setAdminUser();$record = new \stdClass();$record->courseid = 0;$record->categoryid = $category->id;$record->timestart = time() - DAYSECS;$catevent1 = $this->create_calendar_event('category a', $USER->id, 'category', 0, time(), $record);$record = new \stdClass();$record->courseid = 0;$record->categoryid = $category2->id;$record->timestart = time() + DAYSECS;$catevent2 = $this->create_calendar_event('category b', $USER->id, 'category', 0, time(), $record);// Now as student, make sure we get the events of the courses I am enrolled.$this->setUser($user2);$paramevents = array('categoryids' => array($category2b->id));$options = array('timeend' => time() + 7 * WEEKSECS, 'userevents' => false, 'siteevents' => false);$events = core_calendar_external::get_calendar_events($paramevents, $options);$events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);// Should be just one, since there's just one category event of the course I am enrolled (course3 - cat2b).$this->assertEquals(1, count($events['events']));$this->assertEquals($catevent2->id, $events['events'][0]['id']);$this->assertEquals($category2->id, $events['events'][0]['categoryid']);$this->assertEquals(0, count($events['warnings']));// Now get category events but by course (there aren't course events in the course).$paramevents = array('courseids' => array($course3->id));$options = array('timeend' => time() + 7 * WEEKSECS, 'userevents' => false, 'siteevents' => false);$events = core_calendar_external::get_calendar_events($paramevents, $options);$events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);$this->assertEquals(1, count($events['events']));$this->assertEquals($catevent2->id, $events['events'][0]['id']);$this->assertEquals(0, count($events['warnings']));// Empty events in one where I'm not enrolled and one parent category// (parent of a category where this is a course where the user is enrolled).$paramevents = array('categoryids' => array($category2->id, $category->id));$options = array('timeend' => time() + 7 * WEEKSECS, 'userevents' => false, 'siteevents' => false);$events = core_calendar_external::get_calendar_events($paramevents, $options);$events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);$this->assertEquals(1, count($events['events']));$this->assertEquals($catevent2->id, $events['events'][0]['id']);$this->assertEquals(0, count($events['warnings']));// Admin can see all category events.$this->setAdminUser();$paramevents = array('categoryids' => array($category->id, $category2->id, $category2b->id));$options = array('timeend' => time() + 7 * WEEKSECS, 'userevents' => false, 'siteevents' => false);$events = core_calendar_external::get_calendar_events($paramevents, $options);$events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);$this->assertEquals(2, count($events['events']));$this->assertEquals(0, count($events['warnings']));$this->assertEquals($catevent1->id, $events['events'][0]['id']);$this->assertEquals($category->id, $events['events'][0]['categoryid']);$this->assertEquals($catevent2->id, $events['events'][1]['id']);$this->assertEquals($category2->id, $events['events'][1]['categoryid']);}/*** Test get_calendar_events with mathjax in the name.*/public function test_get_calendar_events_with_mathjax(): void {global $USER;$this->resetAfterTest(true);set_config('calendar_adminseesall', 1);$this->setAdminUser();// Enable MathJax filter in content and headings.$this->configure_filters([['name' => 'mathjaxloader', 'state' => TEXTFILTER_ON, 'move' => -1, 'applytostrings' => true],]);// Create a site event with mathjax in the name and description.$siteevent = $this->create_calendar_event('Site Event $$(a+b)=2$$', $USER->id, 'site', 0, time(),['description' => 'Site Event Description $$(a+b)=2$$']);// Now call the WebService.$events = core_calendar_external::get_calendar_events();$events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);// Format the original data.$sitecontext = \context_system::instance();$siteevent->name = $siteevent->format_external_name();list($siteevent->description, $siteevent->descriptionformat) = $siteevent->format_external_text();// Check that the event data is formatted.$this->assertCount(1, $events['events']);$this->assertStringContainsString('<span class="filter_mathjaxloader_equation">', $events['events'][0]['name']);$this->assertStringContainsString('<span class="filter_mathjaxloader_equation">', $events['events'][0]['description']);$this->assertEquals($siteevent->name, $events['events'][0]['name']);$this->assertEquals($siteevent->description, $events['events'][0]['description']);}/*** Test core_calendar_external::create_calendar_events*/public function test_core_create_calendar_events(): void {global $DB, $USER, $SITE;$this->resetAfterTest(true);$this->setAdminUser();// Create a few stuff to test with.$user = $this->getDataGenerator()->create_user();$course = $this->getDataGenerator()->create_course();$record = new \stdClass();$record->courseid = $course->id;$group = $this->getDataGenerator()->create_group($record);$prevcount = $DB->count_records('event');// Let's create a few events.$events = array (array('name' => 'site', 'courseid' => $SITE->id, 'eventtype' => 'site'),array('name' => 'course', 'courseid' => $course->id, 'eventtype' => 'course', 'repeats' => 2),array('name' => 'group', 'courseid' => $course->id, 'groupid' => $group->id, 'eventtype' => 'group'),array('name' => 'user'));$eventsret = core_calendar_external::create_calendar_events($events);$eventsret = external_api::clean_returnvalue(core_calendar_external::create_calendar_events_returns(), $eventsret);// Check to see if things were created properly.$aftercount = $DB->count_records('event');$this->assertEquals($prevcount + 5, $aftercount);$this->assertEquals(5, count($eventsret['events']));$this->assertEquals(0, count($eventsret['warnings']));$sitecontext = \context_system::instance();$coursecontext = \context_course::instance($course->id);$this->setUser($user);$prevcount = $aftercount;$events = array (array('name' => 'course', 'courseid' => $course->id, 'eventtype' => 'course', 'repeats' => 2),array('name' => 'group', 'courseid' => $course->id, 'groupid' => $group->id, 'eventtype' => 'group'),array('name' => 'user'));$role = $DB->get_record('role', array('shortname' => 'student'));$this->getDataGenerator()->enrol_user($user->id, $course->id, $role->id);groups_add_member($group, $user);$this->assignUserCapability('moodle/calendar:manageentries', $coursecontext->id, $role->id);$this->assignUserCapability('moodle/calendar:managegroupentries', $coursecontext->id, $role->id);$eventsret = core_calendar_external::create_calendar_events($events);$eventsret = external_api::clean_returnvalue(core_calendar_external::create_calendar_events_returns(), $eventsret);// Check to see if things were created properly.$aftercount = $DB->count_records('event');$this->assertEquals($prevcount + 4, $aftercount);$this->assertEquals(4, count($eventsret['events']));$this->assertEquals(0, count($eventsret['warnings']));// Check to see nothing was created without proper permission.$this->setGuestUser();$prevcount = $DB->count_records('event');$eventsret = core_calendar_external::create_calendar_events($events);$eventsret = external_api::clean_returnvalue(core_calendar_external::create_calendar_events_returns(), $eventsret);$aftercount = $DB->count_records('event');$this->assertEquals($prevcount, $aftercount);$this->assertEquals(0, count($eventsret['events']));$this->assertEquals(3, count($eventsret['warnings']));$this->setUser($user);$this->unassignUserCapability('moodle/calendar:manageentries', $coursecontext->id, $role->id);$this->unassignUserCapability('moodle/calendar:managegroupentries', $coursecontext->id, $role->id);$prevcount = $DB->count_records('event');$eventsret = core_calendar_external::create_calendar_events($events);$eventsret = external_api::clean_returnvalue(core_calendar_external::create_calendar_events_returns(), $eventsret);$aftercount = $DB->count_records('event');$this->assertEquals($prevcount + 1, $aftercount); // User event.$this->assertEquals(1, count($eventsret['events']));$this->assertEquals(2, count($eventsret['warnings']));}/*** Requesting calendar events from a given time should return all events with a sort* time at or after the requested time. All events prior to that time should not* be return.** If there are no events on or after the given time then an empty result set should* be returned.*/public function test_get_calendar_action_events_by_timesort_after_time(): void {$user = $this->getDataGenerator()->create_user();$course = $this->getDataGenerator()->create_course();$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');$moduleinstance = $generator->create_instance(['course' => $course->id]);$this->getDataGenerator()->enrol_user($user->id, $course->id);$this->resetAfterTest(true);$this->setUser($user);$params = ['type' => CALENDAR_EVENT_TYPE_ACTION,'modulename' => 'assign','instance' => $moduleinstance->id,'courseid' => $course->id,];$event1 = $this->create_calendar_event('Event 1', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 1]));$event2 = $this->create_calendar_event('Event 2', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 2]));$event3 = $this->create_calendar_event('Event 3', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 3]));$event4 = $this->create_calendar_event('Event 4', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 4]));$event5 = $this->create_calendar_event('Event 5', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 5]));$event6 = $this->create_calendar_event('Event 6', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 6]));$event7 = $this->create_calendar_event('Event 7', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 7]));$event8 = $this->create_calendar_event('Event 8', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 8]));$result = core_calendar_external::get_calendar_action_events_by_timesort(5);$result = external_api::clean_returnvalue(core_calendar_external::get_calendar_action_events_by_timesort_returns(),$result);$events = $result['events'];$this->assertCount(4, $events);$this->assertEquals('Event 5', $events[0]['name']);$this->assertEquals('Event 6', $events[1]['name']);$this->assertEquals('Event 7', $events[2]['name']);$this->assertEquals('Event 8', $events[3]['name']);$this->assertEquals($event5->id, $result['firstid']);$this->assertEquals($event8->id, $result['lastid']);$result = core_calendar_external::get_calendar_action_events_by_timesort(9);$result = external_api::clean_returnvalue(core_calendar_external::get_calendar_action_events_by_timesort_returns(),$result);$this->assertEmpty($result['events']);$this->assertNull($result['firstid']);$this->assertNull($result['lastid']);// Requesting action events on behalf of another user.$this->setAdminUser();$result = core_calendar_external::get_calendar_action_events_by_timesort(5, null, 0, 20, false, $user->id);$result = external_api::clean_returnvalue(core_calendar_external::get_calendar_action_events_by_timesort_returns(),$result);$events = $result['events'];$this->assertCount(4, $events);$this->assertEquals('Event 5', $events[0]['name']);$this->assertEquals('Event 6', $events[1]['name']);$this->assertEquals('Event 7', $events[2]['name']);$this->assertEquals('Event 8', $events[3]['name']);$this->assertEquals($event5->id, $result['firstid']);$this->assertEquals($event8->id, $result['lastid']);}/*** Requesting calendar events before a given time should return all events with a sort* time at or before the requested time (inclusive). All events after that time* should not be returned.** If there are no events before the given time then an empty result set should be* returned.*/public function test_get_calendar_action_events_by_timesort_before_time(): void {$user = $this->getDataGenerator()->create_user();$course = $this->getDataGenerator()->create_course();$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');$moduleinstance = $generator->create_instance(['course' => $course->id]);$this->getDataGenerator()->enrol_user($user->id, $course->id);$this->resetAfterTest(true);$this->setUser($user);$params = ['type' => CALENDAR_EVENT_TYPE_ACTION,'modulename' => 'assign','instance' => $moduleinstance->id,'courseid' => $course->id,];$event1 = $this->create_calendar_event('Event 1', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 2]));$event2 = $this->create_calendar_event('Event 2', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 3]));$event3 = $this->create_calendar_event('Event 3', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 4]));$event4 = $this->create_calendar_event('Event 4', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 5]));$event5 = $this->create_calendar_event('Event 5', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 6]));$event6 = $this->create_calendar_event('Event 6', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 7]));$event7 = $this->create_calendar_event('Event 7', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 8]));$event8 = $this->create_calendar_event('Event 8', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 9]));$result = core_calendar_external::get_calendar_action_events_by_timesort(null, 5);$result = external_api::clean_returnvalue(core_calendar_external::get_calendar_action_events_by_timesort_returns(),$result);$events = $result['events'];$this->assertCount(4, $events);$this->assertEquals('Event 1', $events[0]['name']);$this->assertEquals('Event 2', $events[1]['name']);$this->assertEquals('Event 3', $events[2]['name']);$this->assertEquals('Event 4', $events[3]['name']);$this->assertEquals($event1->id, $result['firstid']);$this->assertEquals($event4->id, $result['lastid']);$result = core_calendar_external::get_calendar_action_events_by_timesort(null, 1);$result = external_api::clean_returnvalue(core_calendar_external::get_calendar_action_events_by_timesort_returns(),$result);$this->assertEmpty($result['events']);$this->assertNull($result['firstid']);$this->assertNull($result['lastid']);// Requesting action events on behalf of another user.$this->setAdminUser();$result = core_calendar_external::get_calendar_action_events_by_timesort(null, 5, 0, 20, false, $user->id);$result = external_api::clean_returnvalue(core_calendar_external::get_calendar_action_events_by_timesort_returns(),$result);$events = $result['events'];$this->assertCount(4, $events);$this->assertEquals('Event 1', $events[0]['name']);$this->assertEquals('Event 2', $events[1]['name']);$this->assertEquals('Event 3', $events[2]['name']);$this->assertEquals('Event 4', $events[3]['name']);$this->assertEquals($event1->id, $result['firstid']);$this->assertEquals($event4->id, $result['lastid']);}/*** Test retrieving event that was overridden for a user*/public function test_get_calendar_events_override(): void {$user = $this->getDataGenerator()->create_user();$user2 = $this->getDataGenerator()->create_user();$teacher = $this->getDataGenerator()->create_user();$anotheruser = $this->getDataGenerator()->create_user();$course = $this->getDataGenerator()->create_course();$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');$moduleinstance = $generator->create_instance(['course' => $course->id]);$this->getDataGenerator()->enrol_user($user->id, $course->id, 'student');$this->getDataGenerator()->enrol_user($user2->id, $course->id, 'student');$this->getDataGenerator()->enrol_user($teacher->id, $course->id, 'editingteacher');$this->resetAfterTest(true);$this->setAdminUser();$params = ['type' => CALENDAR_EVENT_TYPE_ACTION,'modulename' => 'assign','instance' => $moduleinstance->id,];$now = time();// Create two events - one for everybody in the course and one only for the first student.$event1 = $this->create_calendar_event('Base event', 0, 'due', 0, $now + DAYSECS, $params + ['courseid' => $course->id]);$event2 = $this->create_calendar_event('User event', $user->id, 'due', 0, $now + 2*DAYSECS, $params + ['courseid' => 0]);// Retrieve course events for the second student - only one "Base event" is returned.$this->setUser($user2);$paramevents = array('courseids' => array($course->id));$options = array ('siteevents' => true, 'userevents' => true);$events = core_calendar_external::get_calendar_events($paramevents, $options);$events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);$this->assertEquals(1, count($events['events']));$this->assertEquals(0, count($events['warnings']));$this->assertEquals('Base event', $events['events'][0]['name']);// Retrieve events for the first student - both events are returned.$this->setUser($user);$events = core_calendar_external::get_calendar_events($paramevents, $options);$events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);$this->assertEquals(2, count($events['events']));$this->assertEquals(0, count($events['warnings']));$this->assertEquals('Base event', $events['events'][0]['name']);$this->assertEquals('User event', $events['events'][1]['name']);// Retrieve events by id as a teacher, 'User event' should be returned since teacher has access to this course.$this->setUser($teacher);$paramevents = ['eventids' => [$event2->id]];$events = core_calendar_external::get_calendar_events($paramevents, $options);$events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);$this->assertEquals(1, count($events['events']));$this->assertEquals(0, count($events['warnings']));$this->assertEquals('User event', $events['events'][0]['name']);// Retrieve events by id as another user, nothing should be returned.$this->setUser($anotheruser);$paramevents = ['eventids' => [$event2->id, $event1->id]];$events = core_calendar_external::get_calendar_events($paramevents, $options);$events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);$this->assertEquals(0, count($events['events']));$this->assertEquals(0, count($events['warnings']));}/*** Requesting calendar events within a given time range should return all events with* a sort time between the lower and upper time bound (inclusive).** If there are no events in the given time range then an empty result set should be* returned.*/public function test_get_calendar_action_events_by_timesort_time_range(): void {$user = $this->getDataGenerator()->create_user();$course = $this->getDataGenerator()->create_course();$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');$moduleinstance = $generator->create_instance(['course' => $course->id]);$this->getDataGenerator()->enrol_user($user->id, $course->id);$this->resetAfterTest(true);$this->setUser($user);$params = ['type' => CALENDAR_EVENT_TYPE_ACTION,'modulename' => 'assign','instance' => $moduleinstance->id,'courseid' => $course->id,];$event1 = $this->create_calendar_event('Event 1', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 1]));$event2 = $this->create_calendar_event('Event 2', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 2]));$event3 = $this->create_calendar_event('Event 3', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 3]));$event4 = $this->create_calendar_event('Event 4', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 4]));$event5 = $this->create_calendar_event('Event 5', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 5]));$event6 = $this->create_calendar_event('Event 6', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 6]));$event7 = $this->create_calendar_event('Event 7', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 7]));$event8 = $this->create_calendar_event('Event 8', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 8]));$result = core_calendar_external::get_calendar_action_events_by_timesort(3, 6);$result = external_api::clean_returnvalue(core_calendar_external::get_calendar_action_events_by_timesort_returns(),$result);$events = $result['events'];$this->assertCount(4, $events);$this->assertEquals('Event 3', $events[0]['name']);$this->assertEquals('Event 4', $events[1]['name']);$this->assertEquals('Event 5', $events[2]['name']);$this->assertEquals('Event 6', $events[3]['name']);$this->assertEquals($event3->id, $result['firstid']);$this->assertEquals($event6->id, $result['lastid']);$result = core_calendar_external::get_calendar_action_events_by_timesort(10, 15);$result = external_api::clean_returnvalue(core_calendar_external::get_calendar_action_events_by_timesort_returns(),$result);$this->assertEmpty($result['events']);$this->assertNull($result['firstid']);$this->assertNull($result['lastid']);}/*** Requesting calendar events within a given time range and a limit and offset should return* the number of events up to the given limit value that have a sort time between the lower* and uppper time bound (inclusive) where the result set is shifted by the offset value.** If there are no events in the given time range then an empty result set should be* returned.*/public function test_get_calendar_action_events_by_timesort_time_limit_offset(): void {$user = $this->getDataGenerator()->create_user();$course = $this->getDataGenerator()->create_course();$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');$moduleinstance = $generator->create_instance(['course' => $course->id]);$this->getDataGenerator()->enrol_user($user->id, $course->id);$this->resetAfterTest(true);$this->setUser($user);$params = ['type' => CALENDAR_EVENT_TYPE_ACTION,'modulename' => 'assign','instance' => $moduleinstance->id,'courseid' => $course->id,];$event1 = $this->create_calendar_event('Event 1', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 1]));$event2 = $this->create_calendar_event('Event 2', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 2]));$event3 = $this->create_calendar_event('Event 3', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 3]));$event4 = $this->create_calendar_event('Event 4', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 4]));$event5 = $this->create_calendar_event('Event 5', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 5]));$event6 = $this->create_calendar_event('Event 6', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 6]));$event7 = $this->create_calendar_event('Event 7', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 7]));$event8 = $this->create_calendar_event('Event 8', $user->id, 'user', 0, 1, array_merge($params, ['timesort' => 8]));$result = core_calendar_external::get_calendar_action_events_by_timesort(2, 7, $event3->id, 2);$result = external_api::clean_returnvalue(core_calendar_external::get_calendar_action_events_by_timesort_returns(),$result);$events = $result['events'];$this->assertCount(2, $events);$this->assertEquals('Event 4', $events[0]['name']);$this->assertEquals('Event 5', $events[1]['name']);$this->assertEquals($event4->id, $result['firstid']);$this->assertEquals($event5->id, $result['lastid']);$result = core_calendar_external::get_calendar_action_events_by_timesort(2, 7, $event5->id, 2);$result = external_api::clean_returnvalue(core_calendar_external::get_calendar_action_events_by_timesort_returns(),$result);$events = $result['events'];$this->assertCount(2, $events);$this->assertEquals('Event 6', $events[0]['name']);$this->assertEquals('Event 7', $events[1]['name']);$this->assertEquals($event6->id, $result['firstid']);$this->assertEquals($event7->id, $result['lastid']);$result = core_calendar_external::get_calendar_action_events_by_timesort(2, 7, $event7->id, 2);$result = external_api::clean_returnvalue(core_calendar_external::get_calendar_action_events_by_timesort_returns(),$result);$this->assertEmpty($result['events']);$this->assertNull($result['firstid']);$this->assertNull($result['lastid']);}/*** Check that it is possible to restrict the calendar events to events where the user is not suspended in the course.*/public function test_get_calendar_action_events_by_timesort_suspended_course(): void {$this->resetAfterTest();$user1 = $this->getDataGenerator()->create_user();$user2 = $this->getDataGenerator()->create_user();$course = $this->getDataGenerator()->create_course();$this->setAdminUser();$lesson = $this->getDataGenerator()->create_module('lesson', ['name' => 'Lesson 1','course' => $course->id,'available' => time(),'deadline' => (time() + (60 * 60 * 24 * 5))]);$this->getDataGenerator()->enrol_user($user1->id, $course->id, null, 'manual', 0, 0, ENROL_USER_SUSPENDED);$this->getDataGenerator()->enrol_user($user2->id, $course->id);$this->setUser($user1);$result = core_calendar_external::get_calendar_action_events_by_timesort(0, null, 0, 20, true);$this->assertEmpty($result->events);$this->setUser($user2);$result = core_calendar_external::get_calendar_action_events_by_timesort(0, null, 0, 20, true);$this->assertCount(1, $result->events);$this->assertEquals('Lesson 1 closes', $result->events[0]->name);}/*** Check that it is possible to get other user's events without the permission.*/public function test_get_calendar_action_events_by_timesort_for_other_users(): void {$this->resetAfterTest();// Create test users.$user1 = $this->getDataGenerator()->create_user(['email' => 'student1@localhost.com']);$user2 = $this->getDataGenerator()->create_user(['email' => 'student2@localhost.com']);// Create test course.$course = $this->getDataGenerator()->create_course();$this->setAdminUser();// Create test activity and make it available only for student2.$lesson = $this->getDataGenerator()->create_module('lesson', ['name' => 'Lesson 1','course' => $course->id,'available' => time(),'deadline' => (time() + (60 * 60 * 24 * 5)),'availability' => '{"op":"&","c":[{"type":"profile","sf":"email","op":"isequalto","v":"student2@localhost.com"}],"showc":[true]}']);// Enrol.$this->getDataGenerator()->enrol_user($user1->id, $course->id);$this->getDataGenerator()->enrol_user($user2->id, $course->id);// Student2 can see the event.$this->setUser($user2);$result = core_calendar_external::get_calendar_action_events_by_timesort(0, null, 0, 20, true);$this->assertCount(1, $result->events);$this->assertEquals('Lesson 1 closes', $result->events[0]->name);// Student1 cannot see the event.$this->setUser($user1);$result = core_calendar_external::get_calendar_action_events_by_timesort(0, null, 0, 20, true);$this->assertEmpty($result->events);// Admin, Manager, Teacher can view student2's data.$this->setAdminUser();$result = core_calendar_external::get_calendar_action_events_by_timesort(0, null, 0, 20, true, $user2->id);$this->assertCount(1, $result->events);$this->assertEquals('Lesson 1 closes', $result->events[0]->name);// Student1 will see an exception if he/she trying to view student2's data.$this->setUser($user1);$this->expectException(\required_capability_exception::class);$this->expectExceptionMessage('error/nopermission');$result = core_calendar_external::get_calendar_action_events_by_timesort(0, null, 0, 20, true, $user2->id);}/*** Requesting calendar events from a given course and time should return all* events with a sort time at or after the requested time. All events prior* to that time should not be return.** If there are no events on or after the given time then an empty result set should* be returned.*/public function test_get_calendar_action_events_by_course_after_time(): void {$user = $this->getDataGenerator()->create_user();$course1 = $this->getDataGenerator()->create_course();$course2 = $this->getDataGenerator()->create_course();$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');$instance1 = $generator->create_instance(['course' => $course1->id]);$instance2 = $generator->create_instance(['course' => $course2->id]);$records = [];$this->getDataGenerator()->enrol_user($user->id, $course1->id);$this->getDataGenerator()->enrol_user($user->id, $course2->id);$this->resetAfterTest(true);$this->setUser($user);for ($i = 1; $i < 19; $i++) {$courseid = ($i < 9) ? $course1->id : $course2->id;$instance = ($i < 9) ? $instance1->id : $instance2->id;$records[] = $this->create_calendar_event(sprintf('Event %d', $i),$user->id,'user',0,1,['type' => CALENDAR_EVENT_TYPE_ACTION,'courseid' => $courseid,'timesort' => $i,'modulename' => 'assign','instance' => $instance,]);}$result = core_calendar_external::get_calendar_action_events_by_course($course1->id, 5);$result = external_api::clean_returnvalue(core_calendar_external::get_calendar_action_events_by_course_returns(),$result);$result = $result['events'];$this->assertCount(4, $result);$this->assertEquals('Event 5', $result[0]['name']);$this->assertEquals('Event 6', $result[1]['name']);$this->assertEquals('Event 7', $result[2]['name']);$this->assertEquals('Event 8', $result[3]['name']);$result = core_calendar_external::get_calendar_action_events_by_course($course1->id, 9);$result = external_api::clean_returnvalue(core_calendar_external::get_calendar_action_events_by_course_returns(),$result);$result = $result['events'];$this->assertEmpty($result);}/*** Requesting calendar events for a course and before a given time should return* all events with a sort time at or before the requested time (inclusive). All* events after that time should not be returned.** If there are no events before the given time then an empty result set should be* returned.*/public function test_get_calendar_action_events_by_course_before_time(): void {$user = $this->getDataGenerator()->create_user();$course1 = $this->getDataGenerator()->create_course();$course2 = $this->getDataGenerator()->create_course();$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');$instance1 = $generator->create_instance(['course' => $course1->id]);$instance2 = $generator->create_instance(['course' => $course2->id]);$records = [];$this->getDataGenerator()->enrol_user($user->id, $course1->id);$this->getDataGenerator()->enrol_user($user->id, $course2->id);$this->resetAfterTest(true);$this->setUser($user);for ($i = 1; $i < 19; $i++) {$courseid = ($i < 9) ? $course1->id : $course2->id;$instance = ($i < 9) ? $instance1->id : $instance2->id;$records[] = $this->create_calendar_event(sprintf('Event %d', $i),$user->id,'user',0,1,['type' => CALENDAR_EVENT_TYPE_ACTION,'courseid' => $courseid,'timesort' => $i + 1,'modulename' => 'assign','instance' => $instance,]);}$result = core_calendar_external::get_calendar_action_events_by_course($course1->id, null, 5);$result = external_api::clean_returnvalue(core_calendar_external::get_calendar_action_events_by_course_returns(),$result);$result = $result['events'];$this->assertCount(4, $result);$this->assertEquals('Event 1', $result[0]['name']);$this->assertEquals('Event 2', $result[1]['name']);$this->assertEquals('Event 3', $result[2]['name']);$this->assertEquals('Event 4', $result[3]['name']);$result = core_calendar_external::get_calendar_action_events_by_course($course1->id, null, 1);$result = external_api::clean_returnvalue(core_calendar_external::get_calendar_action_events_by_course_returns(),$result);$result = $result['events'];$this->assertEmpty($result);}/*** Requesting calendar events for a course and within a given time range should* return all events with a sort time between the lower and upper time bound* (inclusive).** If there are no events in the given time range then an empty result set should be* returned.*/public function test_get_calendar_action_events_by_course_time_range(): void {$user = $this->getDataGenerator()->create_user();$course1 = $this->getDataGenerator()->create_course();$course2 = $this->getDataGenerator()->create_course();$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');$instance1 = $generator->create_instance(['course' => $course1->id]);$instance2 = $generator->create_instance(['course' => $course2->id]);$records = [];$this->getDataGenerator()->enrol_user($user->id, $course1->id);$this->getDataGenerator()->enrol_user($user->id, $course2->id);$this->resetAfterTest(true);$this->setUser($user);for ($i = 1; $i < 19; $i++) {$courseid = ($i < 9) ? $course1->id : $course2->id;$instance = ($i < 9) ? $instance1->id : $instance2->id;$records[] = $this->create_calendar_event(sprintf('Event %d', $i),$user->id,'user',0,1,['type' => CALENDAR_EVENT_TYPE_ACTION,'courseid' => $courseid,'timesort' => $i,'modulename' => 'assign','instance' => $instance,]);}$result = core_calendar_external::get_calendar_action_events_by_course($course1->id, 3, 6);$result = external_api::clean_returnvalue(core_calendar_external::get_calendar_action_events_by_course_returns(),$result);$result = $result['events'];$this->assertCount(4, $result);$this->assertEquals('Event 3', $result[0]['name']);$this->assertEquals('Event 4', $result[1]['name']);$this->assertEquals('Event 5', $result[2]['name']);$this->assertEquals('Event 6', $result[3]['name']);$result = core_calendar_external::get_calendar_action_events_by_course($course1->id, 10, 15);$result = external_api::clean_returnvalue(core_calendar_external::get_calendar_action_events_by_course_returns(),$result);$result = $result['events'];$this->assertEmpty($result);}/*** Requesting calendar events for a course and within a given time range and a limit* and offset should return the number of events up to the given limit value that have* a sort time between the lower and uppper time bound (inclusive) where the result* set is shifted by the offset value.** If there are no events in the given time range then an empty result set should be* returned.*/public function test_get_calendar_action_events_by_course_time_limit_offset(): void {$user = $this->getDataGenerator()->create_user();$course1 = $this->getDataGenerator()->create_course();$course2 = $this->getDataGenerator()->create_course();$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');$instance1 = $generator->create_instance(['course' => $course1->id]);$instance2 = $generator->create_instance(['course' => $course2->id]);$records = [];$this->getDataGenerator()->enrol_user($user->id, $course1->id);$this->getDataGenerator()->enrol_user($user->id, $course2->id);$this->resetAfterTest(true);$this->setUser($user);for ($i = 1; $i < 19; $i++) {$courseid = ($i < 9) ? $course1->id : $course2->id;$instance = ($i < 9) ? $instance1->id : $instance2->id;$records[] = $this->create_calendar_event(sprintf('Event %d', $i),$user->id,'user',0,1,['type' => CALENDAR_EVENT_TYPE_ACTION,'courseid' => $courseid,'timesort' => $i,'modulename' => 'assign','instance' => $instance,]);}$result = core_calendar_external::get_calendar_action_events_by_course($course1->id, 2, 7, $records[2]->id, 2);$result = external_api::clean_returnvalue(core_calendar_external::get_calendar_action_events_by_course_returns(),$result);$result = $result['events'];$this->assertCount(2, $result);$this->assertEquals('Event 4', $result[0]['name']);$this->assertEquals('Event 5', $result[1]['name']);$result = core_calendar_external::get_calendar_action_events_by_course($course1->id, 2, 7, $records[4]->id, 2);$result = external_api::clean_returnvalue(core_calendar_external::get_calendar_action_events_by_course_returns(),$result);$result = $result['events'];$this->assertCount(2, $result);$this->assertEquals('Event 6', $result[0]['name']);$this->assertEquals('Event 7', $result[1]['name']);$result = core_calendar_external::get_calendar_action_events_by_course($course1->id, 2, 7, $records[6]->id, 2);$result = external_api::clean_returnvalue(core_calendar_external::get_calendar_action_events_by_course_returns(),$result);$result = $result['events'];$this->assertEmpty($result);}/*** Test get_calendar_action_events_by_course with search feature*/public function test_get_calendar_action_events_by_course_with_search(): void {// Generate data.$user = $this->getDataGenerator()->create_user();$course = $this->getDataGenerator()->create_course();$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');$instance = $generator->create_instance(['course' => $course->id]);// Enrol.$this->getDataGenerator()->enrol_user($user->id, $course->id);$this->resetAfterTest(true);$this->setUser($user);for ($i = 1; $i < 5; $i++) {$this->create_calendar_event(sprintf('Event %d', $i),$user->id,'user',0,1,['type' => CALENDAR_EVENT_TYPE_ACTION,'courseid' => $course->id,'timesort' => $i,'modulename' => 'assign','instance' => $instance->id,]);}// No result found for fake search.$result = core_calendar_external::get_calendar_action_events_by_course($course->id, null, null, 0, 20, 'Fake search');$result = external_api::clean_returnvalue(core_calendar_external::get_calendar_action_events_by_course_returns(),$result);$result = $result['events'];$this->assertEmpty($result);// Search for event name called 'Event 1'.$result = core_calendar_external::get_calendar_action_events_by_course($course->id, null, null, 0, 20, 'Event 1');$result = external_api::clean_returnvalue(core_calendar_external::get_calendar_action_events_by_course_returns(),$result);$result = $result['events'];$this->assertCount(1, $result);$this->assertEquals('Event 1', $result[0]['name']);// Search for activity type called 'assign'.$result = core_calendar_external::get_calendar_action_events_by_course($course->id, null, null, 0, 20, 'assign');$result = external_api::clean_returnvalue(core_calendar_external::get_calendar_action_events_by_course_returns(),$result);$result = $result['events'];$this->assertCount(4, $result);$this->assertEquals('Event 1', $result[0]['name']);$this->assertEquals('Event 2', $result[1]['name']);$this->assertEquals('Event 3', $result[2]['name']);$this->assertEquals('Event 4', $result[3]['name']);}/*** Test that get_action_events_by_courses will return a list of events for each* course you provided as long as the user is enrolled in the course.*/public function test_get_action_events_by_courses(): void {$user = $this->getDataGenerator()->create_user();$course1 = $this->getDataGenerator()->create_course();$course2 = $this->getDataGenerator()->create_course();$course3 = $this->getDataGenerator()->create_course();$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');$instance1 = $generator->create_instance(['course' => $course1->id]);$instance2 = $generator->create_instance(['course' => $course2->id]);$instance3 = $generator->create_instance(['course' => $course3->id]);$records = [];$mapresult = function($result) {$groupedbycourse = [];foreach ($result['groupedbycourse'] as $group) {$events = $group['events'];$courseid = $group['courseid'];$groupedbycourse[$courseid] = $events;}return $groupedbycourse;};$this->getDataGenerator()->enrol_user($user->id, $course1->id);$this->getDataGenerator()->enrol_user($user->id, $course2->id);$this->resetAfterTest(true);$this->setUser($user);for ($i = 1; $i < 10; $i++) {if ($i < 3) {$courseid = $course1->id;$instance = $instance1->id;} else if ($i < 6) {$courseid = $course2->id;$instance = $instance2->id;} else {$courseid = $course3->id;$instance = $instance3->id;}$records[] = $this->create_calendar_event(sprintf('Event %d', $i),$user->id,'user',0,1,['type' => CALENDAR_EVENT_TYPE_ACTION,'courseid' => $courseid,'timesort' => $i,'modulename' => 'assign','instance' => $instance,]);}$result = core_calendar_external::get_calendar_action_events_by_courses([], 1);$result = external_api::clean_returnvalue(core_calendar_external::get_calendar_action_events_by_courses_returns(),$result);$result = $result['groupedbycourse'];$this->assertEmpty($result);$result = core_calendar_external::get_calendar_action_events_by_courses([$course1->id], 3);$result = external_api::clean_returnvalue(core_calendar_external::get_calendar_action_events_by_courses_returns(),$result);$groupedbycourse = $mapresult($result);$this->assertEmpty($groupedbycourse[$course1->id]);$result = core_calendar_external::get_calendar_action_events_by_courses([$course1->id], 1);$result = external_api::clean_returnvalue(core_calendar_external::get_calendar_action_events_by_courses_returns(),$result);$groupedbycourse = $mapresult($result);$this->assertCount(2, $groupedbycourse[$course1->id]);$this->assertEquals('Event 1', $groupedbycourse[$course1->id][0]['name']);$this->assertEquals('Event 2', $groupedbycourse[$course1->id][1]['name']);$result = core_calendar_external::get_calendar_action_events_by_courses([$course1->id, $course2->id], 1);$result = external_api::clean_returnvalue(core_calendar_external::get_calendar_action_events_by_courses_returns(),$result);$groupedbycourse = $mapresult($result);$this->assertCount(2, $groupedbycourse[$course1->id]);$this->assertEquals('Event 1', $groupedbycourse[$course1->id][0]['name']);$this->assertEquals('Event 2', $groupedbycourse[$course1->id][1]['name']);$this->assertCount(3, $groupedbycourse[$course2->id]);$this->assertEquals('Event 3', $groupedbycourse[$course2->id][0]['name']);$this->assertEquals('Event 4', $groupedbycourse[$course2->id][1]['name']);$this->assertEquals('Event 5', $groupedbycourse[$course2->id][2]['name']);$result = core_calendar_external::get_calendar_action_events_by_courses([$course1->id, $course2->id], 2, 4);$result = external_api::clean_returnvalue(core_calendar_external::get_calendar_action_events_by_courses_returns(),$result);$groupedbycourse = $mapresult($result);$this->assertCount(2, $groupedbycourse);$this->assertCount(1, $groupedbycourse[$course1->id]);$this->assertEquals('Event 2', $groupedbycourse[$course1->id][0]['name']);$this->assertCount(2, $groupedbycourse[$course2->id]);$this->assertEquals('Event 3', $groupedbycourse[$course2->id][0]['name']);$this->assertEquals('Event 4', $groupedbycourse[$course2->id][1]['name']);$result = core_calendar_external::get_calendar_action_events_by_courses([$course1->id, $course2->id], 1, null, 1);$result = external_api::clean_returnvalue(core_calendar_external::get_calendar_action_events_by_courses_returns(),$result);$groupedbycourse = $mapresult($result);$this->assertCount(2, $groupedbycourse);$this->assertCount(1, $groupedbycourse[$course1->id]);$this->assertEquals('Event 1', $groupedbycourse[$course1->id][0]['name']);$this->assertCount(1, $groupedbycourse[$course2->id]);$this->assertEquals('Event 3', $groupedbycourse[$course2->id][0]['name']);}/*** Test get_action_events_by_courses with search feature*/public function test_get_action_events_by_courses_with_search(): void {// Generate data.$user = $this->getDataGenerator()->create_user();$course1 = $this->getDataGenerator()->create_course();$course2 = $this->getDataGenerator()->create_course();$course3 = $this->getDataGenerator()->create_course();$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');$instance1 = $generator->create_instance(['course' => $course1->id]);$instance2 = $generator->create_instance(['course' => $course2->id]);$instance3 = $generator->create_instance(['course' => $course3->id]);$this->getDataGenerator()->enrol_user($user->id, $course1->id);$this->getDataGenerator()->enrol_user($user->id, $course2->id);$this->resetAfterTest(true);$this->setUser($user);$mapresult = function($result) {$groupedbycourse = [];foreach ($result['groupedbycourse'] as $group) {$events = $group['events'];$courseid = $group['courseid'];$groupedbycourse[$courseid] = $events;}return $groupedbycourse;};for ($i = 1; $i < 10; $i++) {if ($i < 3) {$courseid = $course1->id;$instance = $instance1->id;} else if ($i < 6) {$courseid = $course2->id;$instance = $instance2->id;} else {$courseid = $course3->id;$instance = $instance3->id;}$records[] = $this->create_calendar_event(sprintf('Event %d', $i),$user->id,'user',0,1,['type' => CALENDAR_EVENT_TYPE_ACTION,'courseid' => $courseid,'timesort' => $i,'modulename' => 'assign','instance' => $instance,]);}// No result found for fake search.$result = core_calendar_external::get_calendar_action_events_by_courses([$course1->id, $course2->id, $course3->id],1, null, 20, 'Fake search');$result = external_api::clean_returnvalue(core_calendar_external::get_calendar_action_events_by_courses_returns(),$result);$groupedbycourse = $mapresult($result);$this->assertEmpty($groupedbycourse[$course1->id]);$this->assertEmpty($groupedbycourse[$course2->id]);$this->assertArrayNotHasKey($course3->id, $groupedbycourse);// Search for event name called 'Event 1'.$result = core_calendar_external::get_calendar_action_events_by_courses([$course1->id, $course2->id, $course3->id],1, null, 20, 'Event 1');$result = external_api::clean_returnvalue(core_calendar_external::get_calendar_action_events_by_courses_returns(),$result);$groupedbycourse = $mapresult($result);$this->assertArrayNotHasKey($course3->id, $groupedbycourse);$this->assertCount(2, $groupedbycourse);$this->assertCount(1, $groupedbycourse[$course1->id]);$this->assertCount(0, $groupedbycourse[$course2->id]);$this->assertEquals('Event 1', $groupedbycourse[$course1->id][0]['name']);// Search for activity type called 'assign'.$result = core_calendar_external::get_calendar_action_events_by_courses([$course1->id, $course2->id, $course3->id],1, null, 20, 'assign');$result = external_api::clean_returnvalue(core_calendar_external::get_calendar_action_events_by_courses_returns(),$result);$groupedbycourse = $mapresult($result);$this->assertArrayNotHasKey($course3->id, $groupedbycourse);$this->assertCount(2, $groupedbycourse);$this->assertCount(2, $groupedbycourse[$course1->id]);$this->assertCount(3, $groupedbycourse[$course2->id]);$this->assertEquals('Event 1', $groupedbycourse[$course1->id][0]['name']);$this->assertEquals('Event 2', $groupedbycourse[$course1->id][1]['name']);$this->assertEquals('Event 3', $groupedbycourse[$course2->id][0]['name']);$this->assertEquals('Event 4', $groupedbycourse[$course2->id][1]['name']);$this->assertEquals('Event 5', $groupedbycourse[$course2->id][2]['name']);}/*** Test for deleting module events.*/public function test_delete_calendar_events_for_modules(): void {$this->resetAfterTest();$this->setAdminUser();$course = $this->getDataGenerator()->create_course();$nexttime = time() + DAYSECS;$this->getDataGenerator()->create_module('assign', ['course' => $course->id, 'duedate' => $nexttime]);$events = calendar_get_events(time(), $nexttime, true, true, true);$this->assertCount(1, $events);$params = [];foreach ($events as $event) {$params[] = ['eventid' => $event->id,'repeat' => false];}$this->expectException(\moodle_exception::class);core_calendar_external::delete_calendar_events($params);}/*** Updating the event start day should change the date value but leave* the time of day unchanged.*/public function test_update_event_start_day(): void {$generator = $this->getDataGenerator();$user = $generator->create_user();$roleid = $generator->create_role();$context = \context_system::instance();$originalstarttime = new \DateTimeImmutable('2017-01-1T15:00:00+08:00');$newstartdate = new \DateTimeImmutable('2018-02-2T10:00:00+08:00');$expected = new \DateTimeImmutable('2018-02-2T15:00:00+08:00');$generator->role_assign($roleid, $user->id, $context->id);assign_capability('moodle/calendar:manageownentries', CAP_ALLOW, $roleid, $context, true);$this->setUser($user);$this->resetAfterTest(true);$event = $this->create_calendar_event('Test event',$user->id,'user',0,null,['courseid' => 0,'timestart' => $originalstarttime->getTimestamp()]);$result = core_calendar_external::update_event_start_day($event->id, $newstartdate->getTimestamp());$result = external_api::clean_returnvalue(core_calendar_external::update_event_start_day_returns(),$result);$this->assertEquals($expected->getTimestamp(), $result['event']['timestart']);}/*** A user should not be able to edit an event that they don't have* capabilities for.*/public function test_update_event_start_day_no_permission(): void {$generator = $this->getDataGenerator();$user = $generator->create_user();$roleid = $generator->create_role();$context = \context_system::instance();$originalstarttime = new \DateTimeImmutable('2017-01-1T15:00:00+08:00');$newstartdate = new \DateTimeImmutable('2018-02-2T10:00:00+08:00');$expected = new \DateTimeImmutable('2018-02-2T15:00:00+08:00');$generator->role_assign($roleid, $user->id, $context->id);assign_capability('moodle/calendar:manageownentries', CAP_ALLOW, $roleid, $context, true);$this->setUser($user);$this->resetAfterTest(true);$event = $this->create_calendar_event('Test event',$user->id,'user',0,null,['courseid' => 0,'timestart' => $originalstarttime->getTimestamp()]);assign_capability('moodle/calendar:manageownentries', CAP_PROHIBIT, $roleid, $context, true);$this->expectException(\moodle_exception::class);$result = core_calendar_external::update_event_start_day($event->id, $newstartdate->getTimestamp());$result = external_api::clean_returnvalue(core_calendar_external::update_event_start_day_returns(),$result);}/*** A user should not be able to update a module event.*/public function test_update_event_start_day_module_event(): void {$generator = $this->getDataGenerator();$user = $generator->create_user();$course = $generator->create_course();$plugingenerator = $generator->get_plugin_generator('mod_assign');$moduleinstance = $plugingenerator->create_instance(['course' => $course->id]);$roleid = $generator->create_role();$context = \context_course::instance($course->id);$originalstarttime = new \DateTimeImmutable('2017-01-1T15:00:00+08:00');$newstartdate = new \DateTimeImmutable('2018-02-2T10:00:00+08:00');$expected = new \DateTimeImmutable('2018-02-2T15:00:00+08:00');$generator->role_assign($roleid, $user->id, $context->id);$generator->enrol_user($user->id, $course->id);$this->setUser($user);$this->resetAfterTest(true);$event = $this->create_calendar_event('Test event',$user->id,'user',0,null,['modulename' => 'assign','instance' => $moduleinstance->id,'courseid' => $course->id,'timestart' => $originalstarttime->getTimestamp()]);assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);$this->expectException(\moodle_exception::class);$result = core_calendar_external::update_event_start_day($event->id, $newstartdate->getTimestamp());$result = external_api::clean_returnvalue(core_calendar_external::update_event_start_day_returns(),$result);}/*** Submit a request where the time duration until is earlier than the time* start in order to get a validation error from the server.*/public function test_submit_create_update_form_validation_error(): void {$user = $this->getDataGenerator()->create_user();$timestart = new \DateTime();$interval = new \DateInterval("P1D"); // One day.$timedurationuntil = new \DateTime();$timedurationuntil->sub($interval);$formdata = ['id' => 0,'userid' => $user->id,'modulename' => '','instance' => 0,'visible' => 1,'name' => 'Test','timestart' => ['day' => $timestart->format('j'),'month' => $timestart->format('n'),'year' => $timestart->format('Y'),'hour' => $timestart->format('G'),'minute' => 0,],'eventtype' => 'user','description' => ['text' => '','format' => 1,],'location' => 'Test','duration' => 1,'timedurationuntil' => ['day' => $timedurationuntil->format('j'),'month' => $timedurationuntil->format('n'),'year' => $timedurationuntil->format('Y'),'hour' => $timedurationuntil->format('G'),'minute' => 0,]];$formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);$querystring = http_build_query($formdata, '', '&');$this->resetAfterTest(true);$this->setUser($user);$result = external_api::clean_returnvalue(core_calendar_external::submit_create_update_form_returns(),core_calendar_external::submit_create_update_form($querystring));$this->assertTrue($result['validationerror']);}/*** A user with the moodle/calendar:manageownentries capability at the* system context should be able to create a user event.*/public function test_submit_create_update_form_create_user_event(): void {$generator = $this->getDataGenerator();$user = $generator->create_user();$roleid = $generator->create_role();$context = \context_system::instance();$timestart = new \DateTime();$interval = new \DateInterval("P1D"); // One day.$timedurationuntil = new \DateTime();$timedurationuntil->add($interval);$formdata = ['id' => 0,'userid' => $user->id,'modulename' => '','instance' => 0,'visible' => 1,'name' => 'Test','timestart' => ['day' => $timestart->format('j'),'month' => $timestart->format('n'),'year' => $timestart->format('Y'),'hour' => $timestart->format('G'),'minute' => 0,],'eventtype' => 'user','description' => ['text' => '','format' => 1,'itemid' => 0],'location' => 'Test','duration' => 1,'timedurationuntil' => ['day' => $timedurationuntil->format('j'),'month' => $timedurationuntil->format('n'),'year' => $timedurationuntil->format('Y'),'hour' => $timedurationuntil->format('G'),'minute' => 0,]];$formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);$querystring = http_build_query($formdata, '', '&');$generator->role_assign($roleid, $user->id, $context->id);assign_capability('moodle/calendar:manageownentries', CAP_ALLOW, $roleid, $context, true);$user->ignoresesskey = true;$this->resetAfterTest(true);$this->setUser($user);$result = external_api::clean_returnvalue(core_calendar_external::submit_create_update_form_returns(),core_calendar_external::submit_create_update_form($querystring));$event = $result['event'];$this->assertEquals($user->id, $event['userid']);$this->assertEquals($formdata['eventtype'], $event['eventtype']);$this->assertEquals($formdata['name'], $event['name']);}/*** A user without the moodle/calendar:manageownentries capability at the* system context should not be able to create a user event.*/public function test_submit_create_update_form_create_user_event_no_permission(): void {$generator = $this->getDataGenerator();$user = $generator->create_user();$roleid = $generator->create_role();$context = \context_system::instance();$timestart = new \DateTime();$interval = new \DateInterval("P1D"); // One day.$timedurationuntil = new \DateTime();$timedurationuntil->add($interval);$formdata = ['id' => 0,'userid' => $user->id,'modulename' => '','instance' => 0,'visible' => 1,'name' => 'Test','timestart' => ['day' => $timestart->format('j'),'month' => $timestart->format('n'),'year' => $timestart->format('Y'),'hour' => $timestart->format('G'),'minute' => 0,],'eventtype' => 'user','description' => ['text' => '','format' => 1,],'location' => 'Test','duration' => 1,'timedurationuntil' => ['day' => $timedurationuntil->format('j'),'month' => $timedurationuntil->format('n'),'year' => $timedurationuntil->format('Y'),'hour' => $timedurationuntil->format('G'),'minute' => 0,]];$formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);$querystring = http_build_query($formdata, '', '&');$generator->role_assign($roleid, $user->id, $context->id);assign_capability('moodle/calendar:manageownentries', CAP_PROHIBIT, $roleid, $context, true);$user->ignoresesskey = true;$this->resetAfterTest(true);$this->setUser($user);$this->expectException(\moodle_exception::class);external_api::clean_returnvalue(core_calendar_external::submit_create_update_form_returns(),core_calendar_external::submit_create_update_form($querystring));}/*** A user with the moodle/calendar:manageentries capability at the* site course context should be able to create a site event.*/public function test_submit_create_update_form_create_site_event(): void {$generator = $this->getDataGenerator();$user = $generator->create_user();$context = \context_system::instance();$roleid = $generator->create_role();$timestart = new \DateTime();$interval = new \DateInterval("P1D"); // One day.$timedurationuntil = new \DateTime();$timedurationuntil->add($interval);$formdata = ['id' => 0,'userid' => $user->id,'modulename' => '','instance' => 0,'visible' => 1,'name' => 'Test','timestart' => ['day' => $timestart->format('j'),'month' => $timestart->format('n'),'year' => $timestart->format('Y'),'hour' => $timestart->format('G'),'minute' => 0,],'eventtype' => 'site','description' => ['text' => '','format' => 1,'itemid' => 0],'location' => 'Test','duration' => 1,'timedurationuntil' => ['day' => $timedurationuntil->format('j'),'month' => $timedurationuntil->format('n'),'year' => $timedurationuntil->format('Y'),'hour' => $timedurationuntil->format('G'),'minute' => 0,]];$formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);$querystring = http_build_query($formdata, '', '&');$generator->role_assign($roleid, $user->id, $context->id);assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);$user->ignoresesskey = true;$this->resetAfterTest(true);$this->setUser($user);$result = external_api::clean_returnvalue(core_calendar_external::submit_create_update_form_returns(),core_calendar_external::submit_create_update_form($querystring));$event = $result['event'];$this->assertEquals($user->id, $event['userid']);$this->assertEquals($formdata['eventtype'], $event['eventtype']);$this->assertEquals($formdata['name'], $event['name']);}/*** A user without the moodle/calendar:manageentries capability at the* site course context should not be able to create a site event.*/public function test_submit_create_update_form_create_site_event_no_permission(): void {$generator = $this->getDataGenerator();$user = $generator->create_user();$context = \context_course::instance(SITEID);$roleid = $generator->create_role();$timestart = new \DateTime();$interval = new \DateInterval("P1D"); // One day.$timedurationuntil = new \DateTime();$timedurationuntil->add($interval);$formdata = ['id' => 0,'userid' => $user->id,'modulename' => '','instance' => 0,'visible' => 1,'name' => 'Test','timestart' => ['day' => $timestart->format('j'),'month' => $timestart->format('n'),'year' => $timestart->format('Y'),'hour' => $timestart->format('G'),'minute' => 0,],'eventtype' => 'site','description' => ['text' => '','format' => 1,],'location' => 'Test','duration' => 1,'timedurationuntil' => ['day' => $timedurationuntil->format('j'),'month' => $timedurationuntil->format('n'),'year' => $timedurationuntil->format('Y'),'hour' => $timedurationuntil->format('G'),'minute' => 0,]];$formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);$querystring = http_build_query($formdata, '', '&');$generator->role_assign($roleid, $user->id, $context->id);assign_capability('moodle/calendar:manageentries', CAP_PROHIBIT, $roleid, $context, true);$user->ignoresesskey = true;$this->resetAfterTest(true);$this->setUser($user);$result = external_api::clean_returnvalue(core_calendar_external::submit_create_update_form_returns(),core_calendar_external::submit_create_update_form($querystring));$this->assertTrue($result['validationerror']);}/*** A user that has the moodle/calendar:manageentries in a course that they* are enrolled in should be able to create a course event in that course.*/public function test_submit_create_update_form_create_course_event(): void {$generator = $this->getDataGenerator();$user = $generator->create_user();$course = $generator->create_course();$context = \context_course::instance($course->id);$roleid = $generator->create_role();$timestart = new \DateTime();$interval = new \DateInterval("P1D"); // One day.$timedurationuntil = new \DateTime();$timedurationuntil->add($interval);$formdata = ['id' => 0,'userid' => $user->id,'modulename' => '','instance' => 0,'visible' => 1,'name' => 'Test','timestart' => ['day' => $timestart->format('j'),'month' => $timestart->format('n'),'year' => $timestart->format('Y'),'hour' => $timestart->format('G'),'minute' => 0,],'eventtype' => 'course','courseid' => $course->id,'description' => ['text' => '','format' => 1,'itemid' => 0,],'location' => 'Test','duration' => 1,'timedurationuntil' => ['day' => $timedurationuntil->format('j'),'month' => $timedurationuntil->format('n'),'year' => $timedurationuntil->format('Y'),'hour' => $timedurationuntil->format('G'),'minute' => 0,]];$formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);$querystring = http_build_query($formdata, '', '&');$generator->enrol_user($user->id, $course->id, 'student');$generator->role_assign($roleid, $user->id, $context->id);assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);$user->ignoresesskey = true;$this->resetAfterTest(true);$this->setUser($user);$result = external_api::clean_returnvalue(core_calendar_external::submit_create_update_form_returns(),core_calendar_external::submit_create_update_form($querystring));$event = $result['event'];$this->assertEquals($user->id, $event['userid']);$this->assertEquals($formdata['eventtype'], $event['eventtype']);$this->assertEquals($formdata['name'], $event['name']);$this->assertEquals($formdata['courseid'], $event['course']['id']);}/*** A user without the moodle/calendar:manageentries capability in a course* that they are enrolled in should not be able to create a course event in that course.*/public function test_submit_create_update_form_create_course_event_no_permission(): void {$generator = $this->getDataGenerator();$user = $generator->create_user();$course = $generator->create_course();$context = \context_course::instance($course->id);$roleid = $generator->create_role();$timestart = new \DateTime();$interval = new \DateInterval("P1D"); // One day.$timedurationuntil = new \DateTime();$timedurationuntil->add($interval);$formdata = ['id' => 0,'userid' => $user->id,'modulename' => '','instance' => 0,'visible' => 1,'name' => 'Test','timestart' => ['day' => $timestart->format('j'),'month' => $timestart->format('n'),'year' => $timestart->format('Y'),'hour' => $timestart->format('G'),'minute' => 0,],'eventtype' => 'course','courseid' => $course->id,'description' => ['text' => '','format' => 1,],'location' => 'Test','duration' => 1,'timedurationuntil' => ['day' => $timedurationuntil->format('j'),'month' => $timedurationuntil->format('n'),'year' => $timedurationuntil->format('Y'),'hour' => $timedurationuntil->format('G'),'minute' => 0,]];$formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);$querystring = http_build_query($formdata, '', '&');$generator->enrol_user($user->id, $course->id, 'student');$generator->role_assign($roleid, $user->id, $context->id);assign_capability('moodle/calendar:manageentries', CAP_PROHIBIT, $roleid, $context, true);$user->ignoresesskey = true;$this->resetAfterTest(true);$this->setUser($user);$result = external_api::clean_returnvalue(core_calendar_external::submit_create_update_form_returns(),core_calendar_external::submit_create_update_form($querystring));$this->assertTrue($result['validationerror']);}/*** A user should not be able to create an event for a course that they are* not enrolled in.*/public function test_submit_create_update_form_create_course_event_not_enrolled(): void {$generator = $this->getDataGenerator();$user = $generator->create_user();$course = $generator->create_course();$course2 = $generator->create_course();$context = \context_course::instance($course->id);$roleid = $generator->create_role();$timestart = new \DateTime();$interval = new \DateInterval("P1D"); // One day.$timedurationuntil = new \DateTime();$timedurationuntil->add($interval);$formdata = ['id' => 0,'userid' => $user->id,'modulename' => '','instance' => 0,'visible' => 1,'name' => 'Test','timestart' => ['day' => $timestart->format('j'),'month' => $timestart->format('n'),'year' => $timestart->format('Y'),'hour' => $timestart->format('G'),'minute' => 0,],'eventtype' => 'course','courseid' => $course2->id, // Not enrolled.'description' => ['text' => '','format' => 1,],'location' => 'Test','duration' => 1,'timedurationuntil' => ['day' => $timedurationuntil->format('j'),'month' => $timedurationuntil->format('n'),'year' => $timedurationuntil->format('Y'),'hour' => $timedurationuntil->format('G'),'minute' => 0,]];$formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);$querystring = http_build_query($formdata, '', '&');$generator->enrol_user($user->id, $course->id, 'student');$generator->role_assign($roleid, $user->id, $context->id);assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);$user->ignoresesskey = true;$this->resetAfterTest(true);$this->setUser($user);$result = external_api::clean_returnvalue(core_calendar_external::submit_create_update_form_returns(),core_calendar_external::submit_create_update_form($querystring));$this->assertTrue($result['validationerror']);}/*** A user should be able to create an event for a group that they are a member of in* a course in which they are enrolled and have the moodle/calendar:manageentries capability.*/public function test_submit_create_update_form_create_group_event_group_member_manage_course(): void {$generator = $this->getDataGenerator();$user = $generator->create_user();$course = $generator->create_course();$group = $generator->create_group(array('courseid' => $course->id));$context = \context_course::instance($course->id);$roleid = $generator->create_role();$timestart = new \DateTime();$interval = new \DateInterval("P1D"); // One day.$timedurationuntil = new \DateTime();$timedurationuntil->add($interval);$formdata = ['id' => 0,'userid' => $user->id,'modulename' => '','instance' => 0,'visible' => 1,'name' => 'Test','timestart' => ['day' => $timestart->format('j'),'month' => $timestart->format('n'),'year' => $timestart->format('Y'),'hour' => $timestart->format('G'),'minute' => 0,],'eventtype' => 'group','groupid' => $group->id,'groupcourseid' => $course->id,'description' => ['text' => '','format' => 1,'itemid' => 0],'location' => 'Test','duration' => 1,'timedurationuntil' => ['day' => $timedurationuntil->format('j'),'month' => $timedurationuntil->format('n'),'year' => $timedurationuntil->format('Y'),'hour' => $timedurationuntil->format('G'),'minute' => 0,]];$formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);$querystring = http_build_query($formdata, '', '&');$generator->enrol_user($user->id, $course->id, 'student');$generator->role_assign($roleid, $user->id, $context->id);$generator->create_group_member(['groupid' => $group->id, 'userid' => $user->id]);assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);$user->ignoresesskey = true;$this->resetAfterTest(true);$this->setUser($user);$result = external_api::clean_returnvalue(core_calendar_external::submit_create_update_form_returns(),core_calendar_external::submit_create_update_form($querystring));$event = $result['event'];$this->assertEquals($user->id, $event['userid']);$this->assertEquals($formdata['eventtype'], $event['eventtype']);$this->assertEquals($formdata['name'], $event['name']);$this->assertEquals($group->id, $event['groupid']);}/*** A user should be able to create an event for a group that they are a member of in* a course in which they are enrolled and have the moodle/calendar:managegroupentries capability.*/public function test_submit_create_update_form_create_group_event_group_member_manage_group_entries(): void {$generator = $this->getDataGenerator();$user = $generator->create_user();$course = $generator->create_course();$group = $generator->create_group(array('courseid' => $course->id));$context = \context_course::instance($course->id);$roleid = $generator->create_role();$timestart = new \DateTime();$interval = new \DateInterval("P1D"); // One day.$timedurationuntil = new \DateTime();$timedurationuntil->add($interval);$formdata = ['id' => 0,'userid' => $user->id,'modulename' => '','instance' => 0,'visible' => 1,'name' => 'Test','timestart' => ['day' => $timestart->format('j'),'month' => $timestart->format('n'),'year' => $timestart->format('Y'),'hour' => $timestart->format('G'),'minute' => 0,],'eventtype' => 'group','groupid' => $group->id,'groupcourseid' => $course->id,'description' => ['text' => '','format' => 1,'itemid' => 0],'location' => 'Test','duration' => 1,'timedurationuntil' => ['day' => $timedurationuntil->format('j'),'month' => $timedurationuntil->format('n'),'year' => $timedurationuntil->format('Y'),'hour' => $timedurationuntil->format('G'),'minute' => 0,]];$formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);$querystring = http_build_query($formdata, '', '&');$generator->enrol_user($user->id, $course->id, 'student');$generator->role_assign($roleid, $user->id, $context->id);$generator->create_group_member(['groupid' => $group->id, 'userid' => $user->id]);assign_capability('moodle/calendar:manageentries', CAP_PROHIBIT, $roleid, $context, true);assign_capability('moodle/calendar:managegroupentries', CAP_ALLOW, $roleid, $context, true);$user->ignoresesskey = true;$this->resetAfterTest(true);$this->setUser($user);$result = external_api::clean_returnvalue(core_calendar_external::submit_create_update_form_returns(),core_calendar_external::submit_create_update_form($querystring));$event = $result['event'];$this->assertEquals($user->id, $event['userid']);$this->assertEquals($formdata['eventtype'], $event['eventtype']);$this->assertEquals($formdata['name'], $event['name']);$this->assertEquals($group->id, $event['groupid']);}/*** A user should be able to create an event for any group in a course in which* they are enrolled and have the moodle/site:accessallgroups capability.*/public function test_submit_create_update_form_create_group_event_access_all_groups(): void {$generator = $this->getDataGenerator();$user = $generator->create_user();$course = $generator->create_course();$group = $generator->create_group(array('courseid' => $course->id));$context = \context_course::instance($course->id);$roleid = $generator->create_role();$timestart = new \DateTime();$interval = new \DateInterval("P1D"); // One day.$timedurationuntil = new \DateTime();$timedurationuntil->add($interval);$formdata = ['id' => 0,'userid' => $user->id,'modulename' => '','instance' => 0,'visible' => 1,'name' => 'Test','timestart' => ['day' => $timestart->format('j'),'month' => $timestart->format('n'),'year' => $timestart->format('Y'),'hour' => $timestart->format('G'),'minute' => 0,],'eventtype' => 'group','groupid' => $group->id,'groupcourseid' => $course->id,'description' => ['text' => '','format' => 1,'itemid' => 0],'location' => 'Test','duration' => 1,'timedurationuntil' => ['day' => $timedurationuntil->format('j'),'month' => $timedurationuntil->format('n'),'year' => $timedurationuntil->format('Y'),'hour' => $timedurationuntil->format('G'),'minute' => 0,]];$formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);$querystring = http_build_query($formdata, '', '&');$generator->enrol_user($user->id, $course->id, 'student');$generator->role_assign($roleid, $user->id, $context->id);assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $roleid, $context, true);$user->ignoresesskey = true;$this->resetAfterTest(true);$this->setUser($user);$result = external_api::clean_returnvalue(core_calendar_external::submit_create_update_form_returns(),core_calendar_external::submit_create_update_form($querystring));$event = $result['event'];$this->assertEquals($user->id, $event['userid']);$this->assertEquals($formdata['eventtype'], $event['eventtype']);$this->assertEquals($formdata['name'], $event['name']);$this->assertEquals($group->id, $event['groupid']);}/*** A user should not be able to create an event for any group that they are not a* member of in a course in which they are enrolled but don't have the* moodle/site:accessallgroups capability.*/public function test_submit_create_update_form_create_group_event_non_member_no_permission(): void {$generator = $this->getDataGenerator();$user = $generator->create_user();$course = $generator->create_course();$group = $generator->create_group(array('courseid' => $course->id));$context = \context_course::instance($course->id);$roleid = $generator->create_role();$timestart = new \DateTime();$interval = new \DateInterval("P1D"); // One day.$timedurationuntil = new \DateTime();$timedurationuntil->add($interval);$formdata = ['id' => 0,'userid' => $user->id,'modulename' => '','instance' => 0,'visible' => 1,'name' => 'Test','timestart' => ['day' => $timestart->format('j'),'month' => $timestart->format('n'),'year' => $timestart->format('Y'),'hour' => $timestart->format('G'),'minute' => 0,],'eventtype' => 'group','groupid' => $group->id,'groupcourseid' => $course->id,'description' => ['text' => '','format' => 1,],'location' => 'Test','duration' => 1,'timedurationuntil' => ['day' => $timedurationuntil->format('j'),'month' => $timedurationuntil->format('n'),'year' => $timedurationuntil->format('Y'),'hour' => $timedurationuntil->format('G'),'minute' => 0,]];$formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);$querystring = http_build_query($formdata, '', '&');$generator->enrol_user($user->id, $course->id, 'student');$generator->role_assign($roleid, $user->id, $context->id);assign_capability('moodle/calendar:manageentries', CAP_ALLOW, $roleid, $context, true);assign_capability('moodle/site:accessallgroups', CAP_PROHIBIT, $roleid, $context, true);$user->ignoresesskey = true;$this->resetAfterTest(true);$this->setUser($user);$result = external_api::clean_returnvalue(core_calendar_external::submit_create_update_form_returns(),core_calendar_external::submit_create_update_form($querystring));$this->assertTrue($result['validationerror']);}/*** A user should not be able load the calendar monthly view for a course they cannot access.*/public function test_get_calendar_monthly_view_no_course_permission(): void {global $USER;$this->resetAfterTest(true);$this->setAdminUser();$generator = $this->getDataGenerator();$user1 = $generator->create_user();$user2 = $generator->create_user();$course = $generator->create_course();$generator->enrol_user($user1->id, $course->id, 'student');$name = 'Course Event (course' . $course->id . ')';$record = new \stdClass();$record->courseid = $course->id;$courseevent = $this->create_calendar_event($name, $USER->id, 'course', 0, time(), $record);$timestart = new \DateTime();// Admin can load the course.$data = external_api::clean_returnvalue(core_calendar_external::get_calendar_monthly_view_returns(),core_calendar_external::get_calendar_monthly_view($timestart->format('Y'), $timestart->format('n'),$course->id, null, false, true, $timestart->format('j')));$this->assertEquals($data['courseid'], $course->id);// User enrolled in the course can load the course calendar.$this->setUser($user1);$data = external_api::clean_returnvalue(core_calendar_external::get_calendar_monthly_view_returns(),core_calendar_external::get_calendar_monthly_view($timestart->format('Y'), $timestart->format('n'),$course->id, null, false, true, $timestart->format('j')));$this->assertEquals($data['courseid'], $course->id);// User not enrolled in the course cannot load the course calendar.$this->setUser($user2);$this->expectException(\require_login_exception::class);$data = external_api::clean_returnvalue(core_calendar_external::get_calendar_monthly_view_returns(),core_calendar_external::get_calendar_monthly_view($timestart->format('Y'), $timestart->format('n'),$course->id, null, false, false, $timestart->format('j')));}/*** Test get_calendar_monthly_view when a day parameter is provided.*/public function test_get_calendar_monthly_view_with_day_provided(): void {$this->resetAfterTest();$this->setAdminUser();$timestart = new \DateTime();$data = external_api::clean_returnvalue(core_calendar_external::get_calendar_monthly_view_returns(),core_calendar_external::get_calendar_monthly_view($timestart->format('Y'), $timestart->format('n'),SITEID, null, false, true, $timestart->format('j')));$this->assertEquals($data['date']['mday'], $timestart->format('d'));}/*** A user should not be able load the calendar day view for a course they cannot access.*/public function test_get_calendar_day_view_no_course_permission(): void {global $USER;$this->resetAfterTest(true);$this->setAdminUser();$generator = $this->getDataGenerator();$user1 = $generator->create_user();$user2 = $generator->create_user();$course = $generator->create_course();$generator->enrol_user($user1->id, $course->id, 'student');$name = 'Course Event (course' . $course->id . ')';$record = new \stdClass();$record->courseid = $course->id;$courseevent = $this->create_calendar_event($name, $USER->id, 'course', 0, time(), $record);$timestart = new \DateTime();// Admin can load the course.$data = external_api::clean_returnvalue(core_calendar_external::get_calendar_day_view_returns(),core_calendar_external::get_calendar_day_view($timestart->format('Y'), $timestart->format('n'),$timestart->format('j'), $course->id, null));$this->assertEquals($data['courseid'], $course->id);// User enrolled in the course can load the course calendar.$this->setUser($user1);$data = external_api::clean_returnvalue(core_calendar_external::get_calendar_day_view_returns(),core_calendar_external::get_calendar_day_view($timestart->format('Y'), $timestart->format('n'),$timestart->format('j'), $course->id, null));$this->assertEquals($data['courseid'], $course->id);// User not enrolled in the course cannot load the course calendar.$this->setUser($user2);$this->expectException(\require_login_exception::class);$data = external_api::clean_returnvalue(core_calendar_external::get_calendar_day_view_returns(),core_calendar_external::get_calendar_day_view($timestart->format('Y'), $timestart->format('n'),$timestart->format('j'), $course->id, null));}/*** A user should not be able load the calendar upcoming view for a course they cannot access.*/public function test_get_calendar_upcoming_view_no_course_permission(): void {global $USER;$this->resetAfterTest(true);$this->setAdminUser();$generator = $this->getDataGenerator();$user1 = $generator->create_user();$user2 = $generator->create_user();$course = $generator->create_course();$generator->enrol_user($user1->id, $course->id, 'student');$name = 'Course Event (course' . $course->id . ')';$record = new \stdClass();$record->courseid = $course->id;$courseevent = $this->create_calendar_event($name, $USER->id, 'course', 0, time(), $record);// Admin can load the course.$data = external_api::clean_returnvalue(core_calendar_external::get_calendar_upcoming_view_returns(),core_calendar_external::get_calendar_upcoming_view($course->id, null));$this->assertEquals($data['courseid'], $course->id);// User enrolled in the course can load the course calendar.$this->setUser($user1);$data = external_api::clean_returnvalue(core_calendar_external::get_calendar_upcoming_view_returns(),core_calendar_external::get_calendar_upcoming_view($course->id, null));$this->assertEquals($data['courseid'], $course->id);// User not enrolled in the course cannot load the course calendar.$this->setUser($user2);$this->expectException(\require_login_exception::class);$data = external_api::clean_returnvalue(core_calendar_external::get_calendar_upcoming_view_returns(),core_calendar_external::get_calendar_upcoming_view($course->id, null));}/*** A user should not be able load the calendar event for a course they cannot access.*/public function test_get_calendar_event_by_id_no_course_permission(): void {global $USER;$this->resetAfterTest(true);$this->setAdminUser();$generator = $this->getDataGenerator();$user1 = $generator->create_user();$user2 = $generator->create_user();$course = $generator->create_course();$generator->enrol_user($user1->id, $course->id, 'student');$name = 'Course Event (course' . $course->id . ')';$record = new \stdClass();$record->courseid = $course->id;$courseevent = $this->create_calendar_event($name, $USER->id, 'course', 0, time(), $record);// Admin can load the course event.$data = external_api::clean_returnvalue(core_calendar_external::get_calendar_event_by_id_returns(),core_calendar_external::get_calendar_event_by_id($courseevent->id));$this->assertEquals($data['event']['id'], $courseevent->id);// User enrolled in the course can load the course event.$this->setUser($user1);$data = external_api::clean_returnvalue(core_calendar_external::get_calendar_event_by_id_returns(),core_calendar_external::get_calendar_event_by_id($courseevent->id));$this->assertEquals($data['event']['id'], $courseevent->id);// User not enrolled in the course cannot load the course event.$this->setUser($user2);$this->expectException(\moodle_exception::class);$data = external_api::clean_returnvalue(core_calendar_external::get_calendar_event_by_id_returns(),core_calendar_external::get_calendar_event_by_id($courseevent->id));}/*** User data for testing reading calendar events.** @return array*/public function get_calendar_event_by_id_prevent_read_other_users_events_data_provider(): array {$syscontext = \context_system::instance();$managerrole = 'manager';return [[true, false, $syscontext, $managerrole, true],[false, false, $syscontext, $managerrole, false],[false, false, null, null, true],[false, true, null, null, false],];}/*** Prevent user from reading other user's event.** @covers \core_calendar_external::get_calendar_event_by_id* @dataProvider get_calendar_event_by_id_prevent_read_other_users_events_data_provider** @param bool $isadminevent Is admin's event* @param bool $isadmin Is current user admin user* @param null|stdClass $readerrolecontext Reader role context* @param null|string $readerrolename Role name* @param bool $expectexception Should the test throw exception*/public function test_get_calendar_event_by_id_prevent_read_other_users_events(bool $isadminevent, bool $isadmin, ?\stdClass $readerrolecontext,?string $readerrolename, bool $expectexception): void {global $USER, $DB;$this->resetAfterTest();$generator = $this->getDataGenerator();if ($isadminevent) {$this->setAdminUser();} else {$user = $generator->create_user();$this->setUser($user);}$userevent = $this->create_calendar_event('user event', $USER->id, 'user', 0, time());$results = external_api::clean_returnvalue(core_calendar_external::get_calendar_event_by_id_returns(),core_calendar_external::get_calendar_event_by_id($userevent->id));$event = reset($results);$this->assertEquals($userevent->id, $event['id']);if ($isadmin) {$this->setAdminUser();} else {$reader = $generator->create_user();if ($readerrolename && $readerrolecontext) {$managerroleid = $DB->get_field('role', 'id', ['shortname' => $readerrolename]);role_assign($managerroleid, $reader->id, $readerrolecontext->id);}$this->setUser($reader);}if ($expectexception) {// Setup if exception is expected for the test.$this->expectException(\moodle_exception::class);}external_api::clean_returnvalue(core_calendar_external::get_calendar_event_by_id_returns(),core_calendar_external::get_calendar_event_by_id($userevent->id));}/*** User data for testing editing or deleting calendar events.** @return array*/public function edit_or_delete_other_users_events_data_provider(): array {$syscontext = \context_system::instance();$managerrole = 'manager';return [[false, false, $syscontext, $managerrole, false],[false, true, $syscontext, $managerrole, true],[false, false, null, null, true],[true, false, null, null, false],];}/*** Test the behavior of deleting other users' user events.** @dataProvider edit_or_delete_other_users_events_data_provider* @covers \core_calendar_external::delete_calendar_events* @param bool $isadmin Whether the current user is admin.* @param bool $isadminevent Whether it's an admin event or not.* @param stdClass|null $writerrolecontext The reader role context.* @param string|null $writerrolename The role name.* @param bool $expectexception Whether the test should throw an exception or not.*/public function test_delete_other_users_events(bool $isadmin, bool $isadminevent,?\stdClass $writerrolecontext, ?string $writerrolename, bool $expectexception): void {global $DB, $USER;$this->resetAfterTest();$generator = $this->getDataGenerator();if ($isadminevent) {$this->setAdminUser();$user = $USER;} else {$user = $generator->create_user();$this->setUser($user);}$userevent = $this->create_calendar_event('user event', $user->id, 'user', 0, time());if ($isadmin) {$this->setAdminUser();} else {$writer = $generator->create_user();if ($writerrolename && $writerrolecontext) {$managerroleid = $DB->get_field('role', 'id', ['shortname' => $writerrolename]);role_assign($managerroleid, $writer->id, $writerrolecontext->id);}$this->setUser($writer);}if ($expectexception) {$this->expectException(\moodle_exception::class);}$events = [['eventid' => $userevent->id, 'repeat' => 0]];core_calendar_external::delete_calendar_events($events);}/*** Test the behavior of editing other users' user events** @dataProvider edit_or_delete_other_users_events_data_provider* @covers \core_calendar_external::submit_create_update_form* @param bool $isadmin Whether the current user is admin.* @param bool $isadminevent Whether it's an admin event or not.* @param stdClass|null $writerrolecontext The reader role context.* @param string|null $writerrolename The role name.* @param bool $expectexception Whether the test should throw an exception or not.*/public function test_edit_other_users_events(bool $isadmin, bool $isadminevent,?\stdClass $writerrolecontext, ?string $writerrolename, bool $expectexception): void {global $DB, $USER;$this->resetAfterTest();$generator = $this->getDataGenerator();if ($isadminevent) {$this->setAdminUser();$user = $USER;} else {$user = $generator->create_user();}$formdata = ['id' => 0,'userid' => $user->id,'modulename' => '','instance' => 0,'visible' => 1,'eventtype' => 'user','name' => 'Test','timestart' => ['day' => 1,'month' => 1,'year' => 2021,'hour' => 1,'minute' => 0,],'description' => ['text' => 'xxxxx','format' => 1,'itemid' => 0],'location' => 'Test','duration' => 0,];$formdata = \core_calendar\local\event\forms\create::mock_generate_submit_keys($formdata);$querystring = http_build_query($formdata, '', '&');if ($isadmin) {$this->setAdminUser();} else {$writer = $generator->create_user();if ($writerrolename && $writerrolecontext) {$managerroleid = $DB->get_field('role', 'id', ['shortname' => $writerrolename]);role_assign($managerroleid, $writer->id, $writerrolecontext->id);}$this->setUser($writer);}$USER->ignoresesskey = true;if ($expectexception) {$this->expectException(\moodle_exception::class);}core_calendar_external::submit_create_update_form($querystring);}/*** A user should not be able load the calendar events for a category they cannot see.*/public function test_get_calendar_events_hidden_category(): void {global $USER;$this->resetAfterTest(true);$this->setAdminUser();$generator = $this->getDataGenerator();$user1 = $generator->create_user();$category = $generator->create_category(['visible' => 0]);$name = 'Category Event (category: ' . $category->id . ')';$record = new \stdClass();$record->categoryid = $category->id;$categoryevent = $this->create_calendar_event($name, $USER->id, 'category', 0, time(), $record);$events = ['eventids' => [$categoryevent->id]];$options = [];// Admin can load the category event.$data = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(),core_calendar_external::get_calendar_events($events, $options));$this->assertEquals($data['events'][0]['id'], $categoryevent->id);// User with no special permission to see hidden categories will not see the event.$this->setUser($user1);$data = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(),core_calendar_external::get_calendar_events($events, $options));$this->assertCount(0, $data['events']);$this->assertEquals('nopermissions', $data['warnings'][0]['warningcode']);}/*** Test get_calendar_access_information for admins.*/public function test_get_calendar_access_information_for_admins(): void {global $CFG;$this->resetAfterTest(true);$this->setAdminUser();$CFG->calendar_adminseesall = 1;$data = external_api::clean_returnvalue(core_calendar_external::get_calendar_access_information_returns(),core_calendar_external::get_calendar_access_information());$this->assertTrue($data['canmanageownentries']);$this->assertTrue($data['canmanagegroupentries']);$this->assertTrue($data['canmanageentries']);}/*** Test get_calendar_access_information for authenticated users.*/public function test_get_calendar_access_information_for_authenticated_users(): void {$this->resetAfterTest(true);$this->setUser($this->getDataGenerator()->create_user());$data = external_api::clean_returnvalue(core_calendar_external::get_calendar_access_information_returns(),core_calendar_external::get_calendar_access_information());$this->assertTrue($data['canmanageownentries']);$this->assertFalse($data['canmanagegroupentries']);$this->assertFalse($data['canmanageentries']);}/*** Test get_calendar_access_information for student users.*/public function test_get_calendar_access_information_for_student_users(): void {global $DB;$this->resetAfterTest(true);$user = $this->getDataGenerator()->create_user();$course = $this->getDataGenerator()->create_course();$role = $DB->get_record('role', array('shortname' => 'student'));$this->getDataGenerator()->enrol_user($user->id, $course->id, $role->id);$this->setUser($user);$data = external_api::clean_returnvalue(core_calendar_external::get_calendar_access_information_returns(),core_calendar_external::get_calendar_access_information($course->id));$this->assertTrue($data['canmanageownentries']);$this->assertFalse($data['canmanagegroupentries']);$this->assertFalse($data['canmanageentries']);}/*** Test get_calendar_access_information for teacher users.*/public function test_get_calendar_access_information_for_teacher_users(): void {global $DB;$this->resetAfterTest(true);$user = $this->getDataGenerator()->create_user();$course = $this->getDataGenerator()->create_course(['groupmode' => 1]);$role = $DB->get_record('role', array('shortname' => 'editingteacher'));$this->getDataGenerator()->enrol_user($user->id, $course->id, $role->id);$this->getDataGenerator()->create_group(['courseid' => $course->id]);$this->setUser($user);$data = external_api::clean_returnvalue(core_calendar_external::get_calendar_access_information_returns(),core_calendar_external::get_calendar_access_information($course->id));$this->assertTrue($data['canmanageownentries']);$this->assertTrue($data['canmanagegroupentries']);$this->assertTrue($data['canmanageentries']);}/*** Test get_allowed_event_types for admins.*/public function test_get_allowed_event_types_for_admins(): void {global $CFG;$this->resetAfterTest(true);$this->setAdminUser();$CFG->calendar_adminseesall = 1;$data = external_api::clean_returnvalue(core_calendar_external::get_allowed_event_types_returns(),core_calendar_external::get_allowed_event_types());$this->assertEquals(['user', 'site', 'course', 'category'], $data['allowedeventtypes']);}/*** Test get_allowed_event_types for authenticated users.*/public function test_get_allowed_event_types_for_authenticated_users(): void {$this->resetAfterTest(true);$this->setUser($this->getDataGenerator()->create_user());$data = external_api::clean_returnvalue(core_calendar_external::get_allowed_event_types_returns(),core_calendar_external::get_allowed_event_types());$this->assertEquals(['user'], $data['allowedeventtypes']);}/*** Test get_allowed_event_types for student users.*/public function test_get_allowed_event_types_for_student_users(): void {global $DB;$this->resetAfterTest(true);$user = $this->getDataGenerator()->create_user();$course = $this->getDataGenerator()->create_course();$role = $DB->get_record('role', array('shortname' => 'student'));$this->getDataGenerator()->enrol_user($user->id, $course->id, $role->id);$this->setUser($user);$data = external_api::clean_returnvalue(core_calendar_external::get_allowed_event_types_returns(),core_calendar_external::get_allowed_event_types($course->id));$this->assertEquals(['user'], $data['allowedeventtypes']);}/*** Test get_allowed_event_types for teacher users.*/public function test_get_allowed_event_types_for_teacher_users(): void {global $DB;$this->resetAfterTest(true);$user = $this->getDataGenerator()->create_user();$course = $this->getDataGenerator()->create_course(['groupmode' => 1]);$role = $DB->get_record('role', array('shortname' => 'editingteacher'));$this->getDataGenerator()->enrol_user($user->id, $course->id, $role->id);$this->getDataGenerator()->create_group(['courseid' => $course->id]);$this->setUser($user);$data = external_api::clean_returnvalue(core_calendar_external::get_allowed_event_types_returns(),core_calendar_external::get_allowed_event_types($course->id));$this->assertEquals(['user', 'course', 'group'], $data['allowedeventtypes']);}/*** Test get_timestamps with string keys, with and without optional hour/minute values.*/public function test_get_timestamps_string_keys(): void {$this->resetAfterTest(true);$this->setAdminUser();$time1 = new \DateTime('2018-12-30 00:00:00');$time2 = new \DateTime('2019-03-27 23:59:00');$dates = [['key' => 'from','year' => $time1->format('Y'),'month' => $time1->format('m'),'day' => $time1->format('d'),],['key' => 'to','year' => $time2->format('Y'),'month' => (int) $time2->format('m'),'day' => $time2->format('d'),'hour' => $time2->format('H'),'minute' => $time2->format('i'),],];$expectedtimestamps = ['from' => $time1->getTimestamp(),'to' => $time2->getTimestamp(),];$result = core_calendar_external::get_timestamps($dates);$this->assertEquals(['timestamps'], array_keys($result));$this->assertEquals(2, count($result['timestamps']));foreach ($result['timestamps'] as $data) {$this->assertTrue(in_array($data['key'], ['from', 'to']));$this->assertEquals($expectedtimestamps[$data['key']], $data['timestamp']);}}/*** Test get_timestamps with no keys specified, with and without optional hour/minute values.*/public function test_get_timestamps_no_keys(): void {$this->resetAfterTest(true);$this->setAdminUser();$time1 = new \DateTime('2018-12-30 00:00:00');$time2 = new \DateTime('2019-03-27 23:59:00');$dates = [['year' => $time1->format('Y'),'month' => $time1->format('m'),'day' => $time1->format('d'),],['year' => $time2->format('Y'),'month' => (int) $time2->format('m'),'day' => $time2->format('d'),'hour' => $time2->format('H'),'minute' => $time2->format('i'),],];$expectedtimestamps = [0 => $time1->getTimestamp(),1 => $time2->getTimestamp(),];$result = core_calendar_external::get_timestamps($dates);$this->assertEquals(['timestamps'], array_keys($result));$this->assertEquals(2, count($result['timestamps']));foreach ($result['timestamps'] as $data) {$this->assertEquals($expectedtimestamps[$data['key']], $data['timestamp']);}}/*** Test for checking if we receive the correct icon branding.** @covers \core_calendar_external::get_calendar_action_events_by_timesort*/public function test_get_calendar_event_branded(): void {$this->resetAfterTest(true);$user = $this->getDataGenerator()->create_user();$course = $this->getDataGenerator()->create_course();$this->getDataGenerator()->enrol_user($user->id, $course->id);$this->setUser($user);$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');$assign = $generator->create_instance(['course' => $course->id]);$params = ['type' => CALENDAR_EVENT_TYPE_ACTION,'instance' => $assign->id,'courseid' => $course->id,'modulename' => 'assign','timesort' => 1,];$event1 = $this->create_calendar_event('Event 1', $user->id, 'user', 0, 1, $params);$result = core_calendar_external::get_calendar_action_events_by_timesort(0);$result = external_api::clean_returnvalue(core_calendar_external::get_calendar_action_events_by_timesort_returns(),$result);$this->assertCount(1, $result['events']);$this->assertFalse($result['events'][0]['branded']);}}