<?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 () {
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() {
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() {
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);
> $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);
> $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);
> $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);
> $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);
> $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);
> $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);
> $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);
> $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);
> $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);
> $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);
> $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);
> $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);
> $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);
> $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);
> $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);
> $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);
> $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);
> $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);
> $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() {
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);
> $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() {
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);
> $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);
> $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);
> $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);
> $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() {
$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(
> $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(
> $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(
> $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() {
$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(
> $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(
> $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(
> $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() {
$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);
> $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);
> $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);
> $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);
> $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() {
$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(
> $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(
> $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() {
$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(
> $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(
> $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(
> $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() {
$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() {
$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() {
$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(
> $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(
> $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() {
$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(
> $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(
> $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() {
$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(
> $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(
> $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() {
$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(
> $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(
> $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(
> $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
* 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_calendar_action_events_by_course_with_search() {
*/
> // Generate data.
public function test_get_action_events_by_courses() {
> $user = $this->getDataGenerator()->create_user();
$user = $this->getDataGenerator()->create_user();
> $course = $this->getDataGenerator()->create_course();
$course1 = $this->getDataGenerator()->create_course();
> $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$course2 = $this->getDataGenerator()->create_course();
> $instance = $generator->create_instance(['course' => $course->id]);
$course3 = $this->getDataGenerator()->create_course();
>
$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
> // Enrol.
$instance1 = $generator->create_instance(['course' => $course1->id]);
> $this->getDataGenerator()->enrol_user($user->id, $course->id);
$instance2 = $generator->create_instance(['course' => $course2->id]);
> $this->resetAfterTest(true);
$instance3 = $generator->create_instance(['course' => $course3->id]);
> $this->setUser($user);
$records = [];
>
$mapresult = function($result) {
> for ($i = 1; $i < 5; $i++) {
$groupedbycourse = [];
> $this->create_calendar_event(
foreach ($result['groupedbycourse'] as $group) {
> sprintf('Event %d', $i),
$events = $group['events'];
> $user->id,
$courseid = $group['courseid'];
> 'user',
$groupedbycourse[$courseid] = $events;
> 0,
}
> 1,
> [
return $groupedbycourse;
> 'type' => CALENDAR_EVENT_TYPE_ACTION,
};
> 'courseid' => $course->id,
> 'timesort' => $i,
$this->getDataGenerator()->enrol_user($user->id, $course1->id);
> 'modulename' => 'assign',
$this->getDataGenerator()->enrol_user($user->id, $course2->id);
> 'instance' => $instance->id,
$this->resetAfterTest(true);
> ]
$this->setUser($user);
> );
> }
for ($i = 1; $i < 10; $i++) {
>
if ($i < 3) {
> // No result found for fake search.
$courseid = $course1->id;
> $result = core_calendar_external::get_calendar_action_events_by_course($course->id, null, null, 0, 20, 'Fake search');
$instance = $instance1->id;
> $result = external_api::clean_returnvalue(
} else if ($i < 6) {
> core_calendar_external::get_calendar_action_events_by_course_returns(),
$courseid = $course2->id;
> $result
$instance = $instance2->id;
> );
} else {
> $result = $result['events'];
$courseid = $course3->id;
> $this->assertEmpty($result);
$instance = $instance3->id;
>
}
> // 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');
$records[] = $this->create_calendar_event(
> $result = external_api::clean_returnvalue(
sprintf('Event %d', $i),
> core_calendar_external::get_calendar_action_events_by_course_returns(),
$user->id,
> $result
'user',
> );
0,
> $result = $result['events'];
1,
> $this->assertCount(1, $result);
[
> $this->assertEquals('Event 1', $result[0]['name']);
'type' => CALENDAR_EVENT_TYPE_ACTION,
>
'courseid' => $courseid,
> // Search for activity type called 'assign'.
'timesort' => $i,
> $result = core_calendar_external::get_calendar_action_events_by_course($course->id, null, null, 0, 20, 'assign');
'modulename' => 'assign',
> $result = external_api::clean_returnvalue(
'instance' => $instance,
> core_calendar_external::get_calendar_action_events_by_course_returns(),
]
> $result
);
> );
}
> $result = $result['events'];
> $this->assertCount(4, $result);
$result = core_calendar_external::get_calendar_action_events_by_courses([], 1);
> $this->assertEquals('Event 1', $result[0]['name']);
$result = \external_api::clean_returnvalue(
> $this->assertEquals('Event 2', $result[1]['name']);
core_calendar_external::get_calendar_action_events_by_courses_returns(),
> $this->assertEquals('Event 3', $result[2]['name']);
$result
> $this->assertEquals('Event 4', $result[3]['name']);
);
> }
$result = $result['groupedbycourse'];
>
> /**
< $result = \external_api::clean_returnvalue(
> $result = external_api::clean_returnvalue(
$result = core_calendar_external::get_calendar_action_events_by_courses([$course1->id], 3);
< $result = \external_api::clean_returnvalue(
> $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(
> $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(
> $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(
> $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(
> $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
* Test for deleting module events.
> */
*/
> public function test_get_action_events_by_courses_with_search() {
public function test_delete_calendar_events_for_modules() {
> // Generate data.
$this->resetAfterTest();
> $user = $this->getDataGenerator()->create_user();
$this->setAdminUser();
> $course1 = $this->getDataGenerator()->create_course();
$course = $this->getDataGenerator()->create_course();
> $course2 = $this->getDataGenerator()->create_course();
$nexttime = time() + DAYSECS;
> $course3 = $this->getDataGenerator()->create_course();
$this->getDataGenerator()->create_module('assign', ['course' => $course->id, 'duedate' => $nexttime]);
> $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$events = calendar_get_events(time(), $nexttime, true, true, true);
> $instance1 = $generator->create_instance(['course' => $course1->id]);
$this->assertCount(1, $events);
> $instance2 = $generator->create_instance(['course' => $course2->id]);
$params = [];
> $instance3 = $generator->create_instance(['course' => $course3->id]);
foreach ($events as $event) {
>
$params[] = [
> $this->getDataGenerator()->enrol_user($user->id, $course1->id);
'eventid' => $event->id,
> $this->getDataGenerator()->enrol_user($user->id, $course2->id);
'repeat' => false
> $this->resetAfterTest(true);
];
> $this->setUser($user);
}
>
> $mapresult = function($result) {
$this->expectException(\moodle_exception::class);
> $groupedbycourse = [];
core_calendar_external::delete_calendar_events($params);
> foreach ($result['groupedbycourse'] as $group) {
}
> $events = $group['events'];
> $courseid = $group['courseid'];
/**
> $groupedbycourse[$courseid] = $events;
* Updating the event start day should change the date value but leave
> }
* the time of day unchanged.
>
*/
> return $groupedbycourse;
public function test_update_event_start_day() {
> };
$generator = $this->getDataGenerator();
>
$user = $generator->create_user();
> for ($i = 1; $i < 10; $i++) {
$roleid = $generator->create_role();
> if ($i < 3) {
$context = \context_system::instance();
> $courseid = $course1->id;
$originalstarttime = new \DateTimeImmutable('2017-01-1T15:00:00+08:00');
> $instance = $instance1->id;
$newstartdate = new \DateTimeImmutable('2018-02-2T10:00:00+08:00');
> } else if ($i < 6) {
$expected = new \DateTimeImmutable('2018-02-2T15:00:00+08:00');
> $courseid = $course2->id;
> $instance = $instance2->id;
$generator->role_assign($roleid, $user->id, $context->id);
> } else {
assign_capability('moodle/calendar:manageownentries', CAP_ALLOW, $roleid, $context, true);
> $courseid = $course3->id;
> $instance = $instance3->id;
$this->setUser($user);
> }
$this->resetAfterTest(true);
>
> $records[] = $this->create_calendar_event(
$event = $this->create_calendar_event(
> sprintf('Event %d', $i),
'Test event',
> $user->id,
$user->id,
> 'user',
'user',
> 0,
0,
> 1,
null,
> [
[
> 'type' => CALENDAR_EVENT_TYPE_ACTION,
'courseid' => 0,
> 'courseid' => $courseid,
'timestart' => $originalstarttime->getTimestamp()
> 'timesort' => $i,
]
> 'modulename' => 'assign',
);
> 'instance' => $instance,
> ]
$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
> // 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');
$this->assertEquals($expected->getTimestamp(), $result['event']['timestart']);
> $result = external_api::clean_returnvalue(
}
> core_calendar_external::get_calendar_action_events_by_courses_returns(),
> $result
/**
> );
* A user should not be able to edit an event that they don't have
> $groupedbycourse = $mapresult($result);
* capabilities for.
>
*/
> $this->assertEmpty($groupedbycourse[$course1->id]);
public function test_update_event_start_day_no_permission() {
> $this->assertEmpty($groupedbycourse[$course2->id]);
$generator = $this->getDataGenerator();
> $this->assertArrayNotHasKey($course3->id, $groupedbycourse);
$user = $generator->create_user();
>
$roleid = $generator->create_role();
> // Search for event name called 'Event 1'.
$context = \context_system::instance();
> $result = core_calendar_external::get_calendar_action_events_by_courses([$course1->id, $course2->id, $course3->id],
$originalstarttime = new \DateTimeImmutable('2017-01-1T15:00:00+08:00');
> 1, null, 20, 'Event 1');
$newstartdate = new \DateTimeImmutable('2018-02-2T10:00:00+08:00');
> $result = external_api::clean_returnvalue(
$expected = new \DateTimeImmutable('2018-02-2T15:00:00+08:00');
> core_calendar_external::get_calendar_action_events_by_courses_returns(),
> $result
$generator->role_assign($roleid, $user->id, $context->id);
> );
assign_capability('moodle/calendar:manageownentries', CAP_ALLOW, $roleid, $context, true);
> $groupedbycourse = $mapresult($result);
>
$this->setUser($user);
> $this->assertArrayNotHasKey($course3->id, $groupedbycourse);
$this->resetAfterTest(true);
> $this->assertCount(2, $groupedbycourse);
> $this->assertCount(1, $groupedbycourse[$course1->id]);
$event = $this->create_calendar_event(
> $this->assertCount(0, $groupedbycourse[$course2->id]);
'Test event',
> $this->assertEquals('Event 1', $groupedbycourse[$course1->id][0]['name']);
$user->id,
>
'user',
> // Search for activity type called 'assign'.
0,
> $result = core_calendar_external::get_calendar_action_events_by_courses([$course1->id, $course2->id, $course3->id],
null,
> 1, null, 20, 'assign');
[
> $result = external_api::clean_returnvalue(
'courseid' => 0,
> core_calendar_external::get_calendar_action_events_by_courses_returns(),
'timestart' => $originalstarttime->getTimestamp()
> $result
]
> );
);
> $groupedbycourse = $mapresult($result);
>
assign_capability('moodle/calendar:manageownentries', CAP_PROHIBIT, $roleid, $context, true);
> $this->assertArrayNotHasKey($course3->id, $groupedbycourse);
$this->expectException(\moodle_exception::class);
> $this->assertCount(2, $groupedbycourse);
$result = core_calendar_external::update_event_start_day($event->id, $newstartdate->getTimestamp());
> $this->assertCount(2, $groupedbycourse[$course1->id]);
$result = \external_api::clean_returnvalue(
> $this->assertCount(3, $groupedbycourse[$course2->id]);
core_calendar_external::update_event_start_day_returns(),
> $this->assertEquals('Event 1', $groupedbycourse[$course1->id][0]['name']);
$result
> $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']);
/**
> }
* A user should not be able to update a module event.
>
*/
> /**
< $result = \external_api::clean_returnvalue(
> $result = external_api::clean_returnvalue(
< $result = \external_api::clean_returnvalue(
> $result = external_api::clean_returnvalue(
$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(
> $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() {
$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(
> $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() {
$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(
> $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() {
$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(
> 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() {
$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(
> $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() {
$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(
> $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() {
$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(
> $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() {
$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(
> $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() {
$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(
> $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() {
$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(
> $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() {
$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(
> $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() {
$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(
> $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() {
$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(
> $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() {
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(
> $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(
> $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(
> $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() {
$this->resetAfterTest();
$this->setAdminUser();
$timestart = new \DateTime();
< $data = \external_api::clean_returnvalue(
> $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() {
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(
> $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(
> $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(
> $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() {
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(
> $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(
> $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(
> $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() {
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(
> $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(
> $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(
> $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) {
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(
> $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(
> 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) {
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) {
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() {
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(
> $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(
> $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() {
global $CFG;
$this->resetAfterTest(true);
$this->setAdminUser();
$CFG->calendar_adminseesall = 1;
< $data = \external_api::clean_returnvalue(
> $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() {
$this->resetAfterTest(true);
$this->setUser($this->getDataGenerator()->create_user());
< $data = \external_api::clean_returnvalue(
> $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() {
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(
> $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() {
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(
> $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() {
global $CFG;
$this->resetAfterTest(true);
$this->setAdminUser();
$CFG->calendar_adminseesall = 1;
< $data = \external_api::clean_returnvalue(
> $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() {
$this->resetAfterTest(true);
$this->setUser($this->getDataGenerator()->create_user());
< $data = \external_api::clean_returnvalue(
> $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() {
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(
> $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() {
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(
> $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() {
$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() {
$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']);
}
}
}