MDL-58424 core_calendar: moved logic from api.php to lib.php
authorMark Nelson <markn@moodle.com>
Thu, 30 Mar 2017 04:18:32 +0000 (12:18 +0800)
committerDan Poltawski <dan@moodle.com>
Tue, 4 Apr 2017 10:01:52 +0000 (11:01 +0100)
Also moved related PHPUnit tests.

Part of MDL-55611 epic.

23 files changed:
blocks/calendar_month/block_calendar_month.php
blocks/calendar_upcoming/block_calendar_upcoming.php
calendar/classes/api.php
calendar/classes/local/event/factories/event_abstract_factory.php
calendar/classes/local/event/strategies/raw_event_retrieval_strategy.php
calendar/delete.php
calendar/event.php
calendar/export.php
calendar/export_execute.php
calendar/externallib.php
calendar/lib.php
calendar/managesubscriptions.php
calendar/managesubscriptions_form.php
calendar/renderer.php
calendar/set.php
calendar/tests/api_test.php
calendar/tests/calendartype_test.php
calendar/tests/events_test.php
calendar/tests/lib_test.php [new file with mode: 0644]
calendar/view.php
lib/classes/task/calendar_cron_task.php
lib/tests/calendar_cron_task_test.php
user/calendar.php

index a6172f9..cc3d6f6 100644 (file)
@@ -70,25 +70,25 @@ class block_calendar_month extends block_base {
         if ($issite) {
             // Being displayed at site level. This will cause the filter to fall back to auto-detecting
             // the list of courses it will be grabbing events from.
-            $filtercourse = \core_calendar\api::get_default_courses();
+            $filtercourse = calendar_get_default_courses();
         } else {
             // Forcibly filter events to include only those from the particular course we are in.
             $filtercourse = array($courseid => $this->page->course);
         }
 
-        list($courses, $group, $user) = \core_calendar\api::set_filters($filtercourse);
+        list($courses, $group, $user) = calendar_set_filters($filtercourse);
         if ($issite) {
             // For the front page.
-            $this->content->text .= \core_calendar\api::get_mini_calendar($courses, $group, $user, false, false,
+            $this->content->text .= calendar_get_mini($courses, $group, $user, false, false,
                 'frontpage', $courseid, $time);
             // No filters for now.
         } else {
             // For any other course.
-            $this->content->text .= \core_calendar\api::get_mini_calendar($courses, $group, $user, false, false,
+            $this->content->text .= calendar_get_mini($courses, $group, $user, false, false,
                 'course', $courseid, $time);
             $this->content->text .= '<h3 class="eventskey">'.get_string('eventskey', 'calendar').'</h3>';
             $this->content->text .= '<div class="filters calendar_filters">' .
-                \core_calendar\api::get_filter_controls($this->page->url) . '</div>';
+                calendar_filter_controls($this->page->url) . '</div>';
         }
 
         return $this->content;
index 3dab047..858a0e4 100644 (file)
@@ -65,14 +65,14 @@ class block_calendar_upcoming extends block_base {
             if ($courseshown == SITEID) {
                 // Being displayed at site level. This will cause the filter to fall back to auto-detecting
                 // the list of courses it will be grabbing events from.
-                $filtercourse = \core_calendar\api::get_default_courses();
+                $filtercourse = calendar_get_default_courses();
             } else {
                 // Forcibly filter events to include only those from the particular course we are in.
                 $filtercourse = array($courseshown => $this->page->course);
             }
         }
 
-        list($courses, $group, $user) = \core_calendar\api::set_filters($filtercourse);
+        list($courses, $group, $user) = calendar_set_filters($filtercourse);
 
         $defaultlookahead = CALENDAR_DEFAULT_UPCOMING_LOOKAHEAD;
         if (isset($CFG->calendar_lookahead)) {
@@ -85,7 +85,7 @@ class block_calendar_upcoming extends block_base {
             $defaultmaxevents = intval($CFG->calendar_maxevents);
         }
         $maxevents = get_user_preferences('calendar_maxevents', $defaultmaxevents);
-        $events = \core_calendar\api::get_upcoming($courses, $group, $user, $lookahead, $maxevents);
+        $events = calendar_get_upcoming($courses, $group, $user, $lookahead, $maxevents);
 
         if (!empty($this->instance)) {
             $link = 'view.php?view=day&amp;course='.$courseshown.'&amp;';
@@ -120,14 +120,14 @@ class block_calendar_upcoming extends block_base {
             if (!isset($events[$i]->time)) {
                 continue;
             }
-            $events[$i] = \core_calendar\api::add_event_metadata($events[$i]);
+            $events[$i] = calendar_add_event_metadata($events[$i]);
             $content .= '<div class="event"><span class="icon c0">' . $events[$i]->icon . '</span>';
             if (!empty($events[$i]->referer)) {
                 // That's an activity event, so let's provide the hyperlink.
                 $content .= $events[$i]->referer;
             } else {
                 if (!empty($linkhref)) {
-                    $href = \core_calendar\api::get_link_href(new \moodle_url(CALENDAR_URL . $linkhref), 0, 0, 0,
+                    $href = calendar_get_link_href(new \moodle_url(CALENDAR_URL . $linkhref), 0, 0, 0,
                         $events[$i]->timestart);
                     $href->set_anchor('event_' . $events[$i]->id);
                     $content .= \html_writer::link($href, $events[$i]->name);
index a053b9a..18d33f2 100644 (file)
@@ -24,8 +24,6 @@
 
 namespace core_calendar;
 
-use context_course;
-
 defined('MOODLE_INTERNAL') || die();
 
 require_once($CFG->dirroot . '/calendar/lib.php');
@@ -41,632 +39,6 @@ use core_calendar\local\api as local_api;
  */
 class api {
 
-    /**
-     * Return the days of the week.
-     *
-     * @return array array of days
-     */
-    public static function get_days() {
-        $calendartype = type_factory::get_calendar_instance();
-        return $calendartype->get_weekdays();
-    }
-
-    /**
-     * Get the subscription from a given id.
-     *
-     * @param int $id id of the subscription
-     * @return \stdClass Subscription record from DB
-     * @throws \moodle_exception for an invalid id
-     */
-    public static function get_subscription($id) {
-        global $DB;
-
-        $cache = \cache::make('core', 'calendar_subscriptions');
-        $subscription = $cache->get($id);
-        if (empty($subscription)) {
-            $subscription = $DB->get_record('event_subscriptions', array('id' => $id), '*', MUST_EXIST);
-            $cache->set($id, $subscription);
-        }
-
-        return $subscription;
-    }
-
-    /**
-     * Gets the first day of the week.
-     *
-     * @return int
-     */
-    public static function get_starting_weekday() {
-        $calendartype = type_factory::get_calendar_instance();
-        return $calendartype->get_starting_weekday();
-    }
-
-    /**
-     * Generates the HTML for a miniature calendar.
-     *
-     * @param array $courses list of course to list events from
-     * @param array $groups list of group
-     * @param array $users user's info
-     * @param int|bool $calmonth calendar month in numeric, default is set to false
-     * @param int|bool $calyear calendar month in numeric, default is set to false
-     * @param string|bool $placement the place/page the calendar is set to appear - passed on the the controls function
-     * @param int|bool $courseid id of the course the calendar is displayed on - passed on the the controls function
-     * @param int $time the unixtimestamp representing the date we want to view, this is used instead of $calmonth
-     *     and $calyear to support multiple calendars
-     * @return string $content return html table for mini calendar
-     */
-    public static function get_mini_calendar($courses, $groups, $users, $calmonth = false, $calyear = false,
-                                             $placement = false, $courseid = false, $time = 0) {
-        global $CFG, $OUTPUT, $PAGE;
-
-        // Get the calendar type we are using.
-        $calendartype = type_factory::get_calendar_instance();
-
-        $display = new \stdClass;
-
-        // Assume we are not displaying this month for now.
-        $display->thismonth = false;
-
-        $content = '';
-
-        // Do this check for backwards compatibility.
-        // The core should be passing a timestamp rather than month and year.
-        // If a month and year are passed they will be in Gregorian.
-        if (!empty($calmonth) && !empty($calyear)) {
-            // Ensure it is a valid date, else we will just set it to the current timestamp.
-            if (checkdate($calmonth, 1, $calyear)) {
-                $time = make_timestamp($calyear, $calmonth, 1);
-            } else {
-                $time = time();
-            }
-            $date = usergetdate($time);
-            if ($calmonth == $date['mon'] && $calyear == $date['year']) {
-                $display->thismonth = true;
-            }
-            // We can overwrite date now with the date used by the calendar type,
-            // if it is not Gregorian, otherwise there is no need as it is already in Gregorian.
-            if ($calendartype->get_name() != 'gregorian') {
-                $date = $calendartype->timestamp_to_date_array($time);
-            }
-        } else if (!empty($time)) {
-            // Get the specified date in the calendar type being used.
-            $date = $calendartype->timestamp_to_date_array($time);
-            $thisdate = $calendartype->timestamp_to_date_array(time());
-            if ($date['month'] == $thisdate['month'] && $date['year'] == $thisdate['year']) {
-                $display->thismonth = true;
-                // If we are the current month we want to set the date to the current date, not the start of the month.
-                $date = $thisdate;
-            }
-        } else {
-            // Get the current date in the calendar type being used.
-            $time = time();
-            $date = $calendartype->timestamp_to_date_array($time);
-            $display->thismonth = true;
-        }
-
-        list($d, $m, $y) = array($date['mday'], $date['mon'], $date['year']); // This is what we want to display.
-
-        // Get Gregorian date for the start of the month.
-        $gregoriandate = $calendartype->convert_to_gregorian($date['year'], $date['mon'], 1);
-
-        // Store the gregorian date values to be used later.
-        list($gy, $gm, $gd, $gh, $gmin) = array($gregoriandate['year'], $gregoriandate['month'], $gregoriandate['day'],
-            $gregoriandate['hour'], $gregoriandate['minute']);
-
-        // Get the max number of days in this month for this calendar type.
-        $display->maxdays = self::get_days_in_month($m, $y);
-        // Get the starting week day for this month.
-        $startwday = dayofweek(1, $m, $y);
-        // Get the days in a week.
-        $daynames = self::get_days();
-        // Store the number of days in a week.
-        $numberofdaysinweek = $calendartype->get_num_weekdays();
-
-        // Set the min and max weekday.
-        $display->minwday = self::get_starting_weekday();
-        $display->maxwday = $display->minwday + ($numberofdaysinweek - 1);
-
-        // These are used for DB queries, so we want unixtime, so we need to use Gregorian dates.
-        $display->tstart = make_timestamp($gy, $gm, $gd, $gh, $gmin, 0);
-        $display->tend = $display->tstart + ($display->maxdays * DAYSECS) - 1;
-
-        // Align the starting weekday to fall in our display range.
-        // This is simple, not foolproof.
-        if ($startwday < $display->minwday) {
-            $startwday += $numberofdaysinweek;
-        }
-
-        // Get the events matching our criteria. Don't forget to offset the timestamps for the user's TZ.
-        $events = self::get_events($display->tstart, $display->tend, $users, $groups, $courses);
-
-        // Set event course class for course events.
-        if (!empty($events)) {
-            foreach ($events as $eventid => $event) {
-                if (!empty($event->modulename)) {
-                    $cm = get_coursemodule_from_instance($event->modulename, $event->instance);
-                    if (!\core_availability\info_module::is_user_visible($cm, 0, false)) {
-                        unset($events[$eventid]);
-                    }
-                }
-            }
-        }
-
-        // This is either a genius idea or an idiot idea: in order to not complicate things, we use this rule: if, after
-        // possibly removing SITEID from $courses, there is only one course left, then clicking on a day in the month
-        // will also set the $SESSION->cal_courses_shown variable to that one course. Otherwise, we 'd need to add extra
-        // arguments to this function.
-        $hrefparams = array();
-        if (!empty($courses)) {
-            $courses = array_diff($courses, array(SITEID));
-            if (count($courses) == 1) {
-                $hrefparams['course'] = reset($courses);
-            }
-        }
-
-        // We want to have easy access by day, since the display is on a per-day basis.
-        self::get_events_by_day($events, $m, $y, $eventsbyday, $durationbyday, $typesbyday, $courses);
-
-        // Accessibility: added summary and <abbr> elements.
-        $summary = get_string('calendarheading', 'calendar', userdate($display->tstart, get_string('strftimemonthyear')));
-        // Begin table.
-        $content .= '<table class="minicalendar calendartable" summary="' . $summary . '">';
-        if (($placement !== false) && ($courseid !== false)) {
-            $content .= '<caption>' . self::get_top_controls($placement,
-                    array('id' => $courseid, 'time' => $time)) . '</caption>';
-        }
-        $content .= '<tr class="weekdays">'; // Header row: day names.
-
-        // Print out the names of the weekdays.
-        for ($i = $display->minwday; $i <= $display->maxwday; $i++) {
-            $pos = $i % $numberofdaysinweek;
-            $content .= '<th scope="col"><abbr title="' . $daynames[$pos]['fullname'] . '">' .
-                $daynames[$pos]['shortname'] . "</abbr></th>\n";
-        }
-
-        $content .= '</tr><tr>'; // End of day names; prepare for day numbers.
-
-        // For the table display. $week is the row; $dayweek is the column.
-        $dayweek = $startwday;
-
-        // Padding (the first week may have blank days in the beginning).
-        for ($i = $display->minwday; $i < $startwday; ++$i) {
-            $content .= '<td class="dayblank">&nbsp;</td>' ."\n";
-        }
-
-        $weekend = CALENDAR_DEFAULT_WEEKEND;
-        if (isset($CFG->calendar_weekend)) {
-            $weekend = intval($CFG->calendar_weekend);
-        }
-
-        // Now display all the calendar.
-        $daytime = strtotime('-1 day', $display->tstart);
-        for ($day = 1; $day <= $display->maxdays; ++$day, ++$dayweek) {
-            $cellattributes = array();
-            $daytime = strtotime('+1 day', $daytime);
-            if ($dayweek > $display->maxwday) {
-                // We need to change week (table row).
-                $content .= '</tr><tr>';
-                $dayweek = $display->minwday;
-            }
-
-            // Reset vars.
-            if ($weekend & (1 << ($dayweek % $numberofdaysinweek))) {
-                // Weekend. This is true no matter what the exact range is.
-                $class = 'weekend day';
-            } else {
-                // Normal working day.
-                $class = 'day';
-            }
-
-            $eventids = array();
-            if (!empty($eventsbyday[$day])) {
-                $eventids = $eventsbyday[$day];
-            }
-
-            if (!empty($durationbyday[$day])) {
-                $eventids = array_unique(array_merge($eventids, $durationbyday[$day]));
-            }
-
-            $finishclass = false;
-
-            if (!empty($eventids)) {
-                // There is at least one event on this day.
-                $class .= ' hasevent';
-                $hrefparams['view'] = 'day';
-                $dayhref = self::get_link_href(new \moodle_url(CALENDAR_URL . 'view.php', $hrefparams), 0, 0, 0, $daytime);
-
-                $popupcontent = '';
-                foreach ($eventids as $eventid) {
-                    if (!isset($events[$eventid])) {
-                        continue;
-                    }
-                    $event = new \calendar_event($events[$eventid]);
-                    $popupalt  = '';
-                    $component = 'moodle';
-                    if (!empty($event->modulename)) {
-                        $popupicon = 'icon';
-                        $popupalt  = $event->modulename;
-                        $component = $event->modulename;
-                    } else if ($event->courseid == SITEID) { // Site event.
-                        $popupicon = 'i/siteevent';
-                    } else if ($event->courseid != 0 && $event->courseid != SITEID
-                        && $event->groupid == 0) { // Course event.
-                        $popupicon = 'i/courseevent';
-                    } else if ($event->groupid) { // Group event.
-                        $popupicon = 'i/groupevent';
-                    } else { // Must be a user event.
-                        $popupicon = 'i/userevent';
-                    }
-
-                    if ($event->timeduration) {
-                        $startdate = $calendartype->timestamp_to_date_array($event->timestart);
-                        $enddate = $calendartype->timestamp_to_date_array($event->timestart + $event->timeduration - 1);
-                        if ($enddate['mon'] == $m && $enddate['year'] == $y && $enddate['mday'] == $day) {
-                            $finishclass = true;
-                        }
-                    }
-
-                    $dayhref->set_anchor('event_' . $event->id);
-
-                    $popupcontent .= \html_writer::start_tag('div');
-                    $popupcontent .= $OUTPUT->pix_icon($popupicon, $popupalt, $component);
-                    // Show ical source if needed.
-                    if (!empty($event->subscription) && $CFG->calendar_showicalsource) {
-                        $a = new \stdClass();
-                        $a->name = format_string($event->name, true);
-                        $a->source = $event->subscription->name;
-                        $name = get_string('namewithsource', 'calendar', $a);
-                    } else {
-                        if ($finishclass) {
-                            $samedate = $startdate['mon'] == $enddate['mon'] &&
-                                $startdate['year'] == $enddate['year'] &&
-                                $startdate['mday'] == $enddate['mday'];
-
-                            if ($samedate) {
-                                $name = format_string($event->name, true);
-                            } else {
-                                $name = format_string($event->name, true) . ' (' . get_string('eventendtime', 'calendar') . ')';
-                            }
-                        } else {
-                            $name = format_string($event->name, true);
-                        }
-                    }
-                    $popupcontent .= \html_writer::link($dayhref, $name);
-                    $popupcontent .= \html_writer::end_tag('div');
-                }
-
-                if ($display->thismonth && $day == $d) {
-                    $popupdata = self::get_popup(true, $daytime, $popupcontent);
-                } else {
-                    $popupdata = self::get_popup(false, $daytime, $popupcontent);
-                }
-
-                // Class and cell content.
-                if (isset($typesbyday[$day]['startglobal'])) {
-                    $class .= ' calendar_event_global';
-                } else if (isset($typesbyday[$day]['startcourse'])) {
-                    $class .= ' calendar_event_course';
-                } else if (isset($typesbyday[$day]['startgroup'])) {
-                    $class .= ' calendar_event_group';
-                } else if (isset($typesbyday[$day]['startuser'])) {
-                    $class .= ' calendar_event_user';
-                }
-                if ($finishclass) {
-                    $class .= ' duration_finish';
-                }
-                $data = array(
-                    'url' => $dayhref,
-                    'day' => $day,
-                    'content' => $popupdata['data-core_calendar-popupcontent'],
-                    'title' => $popupdata['data-core_calendar-title']
-                );
-                $cell = $OUTPUT->render_from_template('core_calendar/minicalendar_day_link', $data);
-            } else {
-                $cell = $day;
-            }
-
-            $durationclass = false;
-            if (isset($typesbyday[$day]['durationglobal'])) {
-                $durationclass = ' duration_global';
-            } else if (isset($typesbyday[$day]['durationcourse'])) {
-                $durationclass = ' duration_course';
-            } else if (isset($typesbyday[$day]['durationgroup'])) {
-                $durationclass = ' duration_group';
-            } else if (isset($typesbyday[$day]['durationuser'])) {
-                $durationclass = ' duration_user';
-            }
-            if ($durationclass) {
-                $class .= ' duration ' . $durationclass;
-            }
-
-            // If event has a class set then add it to the table day <td> tag.
-            // Note: only one colour for minicalendar.
-            if (isset($eventsbyday[$day])) {
-                foreach ($eventsbyday[$day] as $eventid) {
-                    if (!isset($events[$eventid])) {
-                        continue;
-                    }
-                    $event = $events[$eventid];
-                    if (!empty($event->class)) {
-                        $class .= ' ' . $event->class;
-                    }
-                    break;
-                }
-            }
-
-            if ($display->thismonth && $day == $d) {
-                // The current cell is for today - add appropriate classes and additional information for styling.
-                $class .= ' today';
-                $today = get_string('today', 'calendar') . ' ' . userdate(time(), get_string('strftimedayshort'));
-
-                if (!isset($eventsbyday[$day]) && !isset($durationbyday[$day])) {
-                    $class .= ' eventnone';
-                    $popupdata = self::get_popup(true, false);
-                    $data = array(
-                        'url' => '#',
-                        'day' => $day,
-                        'content' => $popupdata['data-core_calendar-popupcontent'],
-                        'title' => $popupdata['data-core_calendar-title']
-                    );
-                    $cell = $OUTPUT->render_from_template('core_calendar/minicalendar_day_link', $data);
-                }
-                $cell = get_accesshide($today . ' ') . $cell;
-            }
-
-            // Just display it.
-            $cellattributes['class'] = $class;
-            $content .= \html_writer::tag('td', $cell, $cellattributes);
-        }
-
-        // Padding (the last week may have blank days at the end).
-        for ($i = $dayweek; $i <= $display->maxwday; ++$i) {
-            $content .= '<td class="dayblank">&nbsp;</td>';
-        }
-        $content .= '</tr>'; // Last row ends.
-
-        $content .= '</table>'; // Tabular display of days ends.
-        return $content;
-    }
-
-    /**
-     * Gets the calendar popup.
-     *
-     * @param bool $today false except when called on the current day.
-     * @param mixed $timestart $events[$eventid]->timestart, OR false if there are no events.
-     * @param string $popupcontent content for the popup window/layout.
-     * @return string eventid for the calendar_tooltip popup window/layout.
-     */
-    public static function get_popup($today = false, $timestart, $popupcontent = '') {
-        $popupcaption = '';
-        if ($today) {
-            $popupcaption = get_string('today', 'calendar') . ' ';
-        }
-
-        if (false === $timestart) {
-            $popupcaption .= userdate(time(), get_string('strftimedayshort'));
-            $popupcontent = get_string('eventnone', 'calendar');
-
-        } else {
-            $popupcaption .= get_string('eventsfor', 'calendar', userdate($timestart, get_string('strftimedayshort')));
-        }
-
-        return array(
-            'data-core_calendar-title' => $popupcaption,
-            'data-core_calendar-popupcontent' => $popupcontent,
-        );
-    }
-
-    /**
-     * Gets the calendar upcoming events.
-     *
-     * @param array $courses array of courses
-     * @param array|int|bool $groups array of groups, group id or boolean for all/no group events
-     * @param array|int|bool $users array of users, user id or boolean for all/no user events
-     * @param int $daysinfuture number of days in the future we 'll look
-     * @param int $maxevents maximum number of events
-     * @param int $fromtime start time
-     * @return array $output array of upcoming events
-     */
-    public static function get_upcoming($courses, $groups, $users, $daysinfuture, $maxevents, $fromtime = 0) {
-        global $COURSE;
-
-        $display = new \stdClass;
-        $display->range = $daysinfuture; // How many days in the future we 'll look.
-        $display->maxevents = $maxevents;
-
-        $output = array();
-
-        $processed = 0;
-        $now = time(); // We 'll need this later.
-        $usermidnighttoday = usergetmidnight($now);
-
-        if ($fromtime) {
-            $display->tstart = $fromtime;
-        } else {
-            $display->tstart = $usermidnighttoday;
-        }
-
-        // This works correctly with respect to the user's DST, but it is accurate
-        // only because $fromtime is always the exact midnight of some day!
-        $display->tend = usergetmidnight($display->tstart + DAYSECS * $display->range + 3 * HOURSECS) - 1;
-
-        // Get the events matching our criteria.
-        $events = self::get_events($display->tstart, $display->tend, $users, $groups, $courses);
-
-        // This is either a genius idea or an idiot idea: in order to not complicate things, we use this rule: if, after
-        // possibly removing SITEID from $courses, there is only one course left, then clicking on a day in the month
-        // will also set the $SESSION->cal_courses_shown variable to that one course. Otherwise, we 'd need to add extra
-        // arguments to this function.
-        $hrefparams = array();
-        if (!empty($courses)) {
-            $courses = array_diff($courses, array(SITEID));
-            if (count($courses) == 1) {
-                $hrefparams['course'] = reset($courses);
-            }
-        }
-
-        if ($events !== false) {
-            $modinfo = get_fast_modinfo($COURSE);
-            foreach ($events as $event) {
-                if (!empty($event->modulename)) {
-                    if ($event->courseid == $COURSE->id) {
-                        if (isset($modinfo->instances[$event->modulename][$event->instance])) {
-                            $cm = $modinfo->instances[$event->modulename][$event->instance];
-                            if (!$cm->uservisible) {
-                                continue;
-                            }
-                        }
-                    } else {
-                        if (!$cm = get_coursemodule_from_instance($event->modulename, $event->instance)) {
-                            continue;
-                        }
-                        if (!\core_availability\info_module::is_user_visible($cm, 0, false)) {
-                            continue;
-                        }
-                    }
-                }
-
-                if ($processed >= $display->maxevents) {
-                    break;
-                }
-
-                $event->time = self::get_format_event_time($event, $now, $hrefparams);
-                $output[] = $event;
-                $processed++;
-            }
-        }
-
-        return $output;
-    }
-
-    /**
-     * Get a HTML link to a course.
-     *
-     * @param int $courseid the course id
-     * @return string a link to the course (as HTML); empty if the course id is invalid
-     */
-    public static function get_courselink($courseid) {
-        if (!$courseid) {
-            return '';
-        }
-
-        self::get_course_cached($coursecache, $courseid);
-        $context = \context_course::instance($courseid);
-        $fullname = format_string($coursecache[$courseid]->fullname, true, array('context' => $context));
-        $url = new \moodle_url('/course/view.php', array('id' => $courseid));
-        $link = \html_writer::link($url, $fullname);
-
-        return $link;
-    }
-
-    /**
-     * Get current module cache.
-     *
-     * @param array $modulecache in memory module cache
-     * @param string $modulename name of the module
-     * @param int $instance module instance number
-     * @return \stdClass|bool $module information
-     */
-    public static function get_module_cached(&$modulecache, $modulename, $instance) {
-        if (!isset($modulecache[$modulename . '_' . $instance])) {
-            $modulecache[$modulename . '_' . $instance] = get_coursemodule_from_instance($modulename, $instance);
-        }
-
-        return $modulecache[$modulename . '_' . $instance];
-    }
-
-    /**
-     * Get current course cache.
-     *
-     * @param array $coursecache list of course cache
-     * @param int $courseid id of the course
-     * @return \stdClass $coursecache[$courseid] return the specific course cache
-     */
-    public static function get_course_cached(&$coursecache, $courseid) {
-        if (!isset($coursecache[$courseid])) {
-            $coursecache[$courseid] = get_course($courseid);
-        }
-        return $coursecache[$courseid];
-    }
-
-    /**
-     * Get group from groupid for calendar display.
-     *
-     * @param int $groupid
-     * @return \stdClass group object with fields 'id', 'name' and 'courseid'
-     */
-    public static function get_group_cached($groupid) {
-        static $groupscache = array();
-        if (!isset($groupscache[$groupid])) {
-            $groupscache[$groupid] = groups_get_group($groupid, 'id,name,courseid');
-        }
-        return $groupscache[$groupid];
-    }
-
-    /**
-     * Add calendar event metadata.
-     *
-     * @param \stdClass $event event info
-     * @return \stdClass $event metadata
-     */
-    public static function add_event_metadata($event) {
-        global $CFG, $OUTPUT;
-
-        // Support multilang in event->name.
-        $event->name = format_string($event->name, true);
-
-        if (!empty($event->modulename)) { // Activity event.
-            // The module name is set. I will assume that it has to be displayed, and
-            // also that it is an automatically-generated event. And of course that the
-            // fields for get_coursemodule_from_instance are set correctly.
-            $module = self::get_module_cached($coursecache, $event->modulename, $event->instance);
-
-            if ($module === false) {
-                return;
-            }
-
-            $modulename = get_string('modulename', $event->modulename);
-            if (get_string_manager()->string_exists($event->eventtype, $event->modulename)) {
-                // Will be used as alt text if the event icon.
-                $eventtype = get_string($event->eventtype, $event->modulename);
-            } else {
-                $eventtype = '';
-            }
-            $icon = $OUTPUT->image_url('icon', $event->modulename) . '';
-
-            $event->icon = '<img src="' . $icon . '" alt="' . $eventtype . '" title="' . $modulename . '" class="icon" />';
-            $event->referer = '<a href="' . $CFG->wwwroot . '/mod/' . $event->modulename . '/view.php?id=' .
-                $module->id . '">' . $event->name . '</a>';
-            $event->courselink = self::get_courselink($module->course);
-            $event->cmid = $module->id;
-        } else if ($event->courseid == SITEID) { // Site event.
-            $event->icon = '<img src="' . $OUTPUT->image_url('i/siteevent') . '" alt="' .
-                get_string('globalevent', 'calendar') . '" class="icon" />';
-            $event->cssclass = 'calendar_event_global';
-        } else if ($event->courseid != 0 && $event->courseid != SITEID && $event->groupid == 0) { // Course event.
-            $event->icon = '<img src="' . $OUTPUT->image_url('i/courseevent') . '" alt="' .
-                get_string('courseevent', 'calendar') . '" class="icon" />';
-            $event->courselink = self::get_courselink($event->courseid);
-            $event->cssclass = 'calendar_event_course';
-        } else if ($event->groupid) { // Group event.
-            if ($group = self::get_group_cached($event->groupid)) {
-                $groupname = format_string($group->name, true, \context_course::instance($group->courseid));
-            } else {
-                $groupname = '';
-            }
-            $event->icon = \html_writer::empty_tag('image', array('src' => $OUTPUT->image_url('i/groupevent'),
-                'alt' => get_string('groupevent', 'calendar'), 'title' => $groupname, 'class' => 'icon'));
-            $event->courselink = self::get_courselink($event->courseid) . ', ' . $groupname;
-            $event->cssclass = 'calendar_event_group';
-        } else if ($event->userid) { // User event.
-            $event->icon = '<img src="' . $OUTPUT->image_url('i/userevent') . '" alt="' .
-                get_string('userevent', 'calendar') . '" class="icon" />';
-            $event->cssclass = 'calendar_event_user';
-        }
-
-        return $event;
-    }
-
     /**
      * Get calendar events
      *
@@ -715,1464 +87,6 @@ class api {
         }, []);
     }
 
-    /**
-     * Get calendar events by id.
-     *
-     * @param array $eventids list of event ids
-     * @return array Array of event entries, empty array if nothing found
-     */
-    public static function get_events_by_id($eventids) {
-        global $DB;
-
-        if (!is_array($eventids) || empty($eventids)) {
-            return array();
-        }
-
-        list($wheresql, $params) = $DB->get_in_or_equal($eventids);
-        $wheresql = "id $wheresql";
-
-        return $DB->get_records_select('event', $wheresql, $params);
-    }
-
-    /**
-     * Get control options for calendar.
-     *
-     * @param string $type of calendar
-     * @param array $data calendar information
-     * @return string $content return available control for the calender in html
-     */
-    public static function get_top_controls($type, $data) {
-        global $PAGE, $OUTPUT;
-
-        // Get the calendar type we are using.
-        $calendartype = type_factory::get_calendar_instance();
-
-        $content = '';
-
-        // Ensure course id passed if relevant.
-        $courseid = '';
-        if (!empty($data['id'])) {
-            $courseid = '&amp;course=' . $data['id'];
-        }
-
-        // If we are passing a month and year then we need to convert this to a timestamp to
-        // support multiple calendars. No where in core should these be passed, this logic
-        // here is for third party plugins that may use this function.
-        if (!empty($data['m']) && !empty($date['y'])) {
-            if (!isset($data['d'])) {
-                $data['d'] = 1;
-            }
-            if (!checkdate($data['m'], $data['d'], $data['y'])) {
-                $time = time();
-            } else {
-                $time = make_timestamp($data['y'], $data['m'], $data['d']);
-            }
-        } else if (!empty($data['time'])) {
-            $time = $data['time'];
-        } else {
-            $time = time();
-        }
-
-        // Get the date for the calendar type.
-        $date = $calendartype->timestamp_to_date_array($time);
-
-        $urlbase = $PAGE->url;
-
-        // We need to get the previous and next months in certain cases.
-        if ($type == 'frontpage' || $type == 'course' || $type == 'month') {
-            $prevmonth = self::get_prev_month($date['mon'], $date['year']);
-            $prevmonthtime = $calendartype->convert_to_gregorian($prevmonth[1], $prevmonth[0], 1);
-            $prevmonthtime = make_timestamp($prevmonthtime['year'], $prevmonthtime['month'], $prevmonthtime['day'],
-                $prevmonthtime['hour'], $prevmonthtime['minute']);
-
-            $nextmonth = self::get_next_month($date['mon'], $date['year']);
-            $nextmonthtime = $calendartype->convert_to_gregorian($nextmonth[1], $nextmonth[0], 1);
-            $nextmonthtime = make_timestamp($nextmonthtime['year'], $nextmonthtime['month'], $nextmonthtime['day'],
-                $nextmonthtime['hour'], $nextmonthtime['minute']);
-        }
-
-        switch ($type) {
-            case 'frontpage':
-                $prevlink = self::get_link_previous(get_string('monthprev', 'access'), $urlbase, false, false, false,
-                    true, $prevmonthtime);
-                $nextlink = self::get_link_next(get_string('monthnext', 'access'), $urlbase, false, false, false, true,
-                    $nextmonthtime);
-                $calendarlink = self::get_link_href(new \moodle_url(CALENDAR_URL . 'view.php', array('view' => 'month')),
-                    false, false, false, $time);
-
-                if (!empty($data['id'])) {
-                    $calendarlink->param('course', $data['id']);
-                }
-
-                $right = $nextlink;
-
-                $content .= \html_writer::start_tag('div', array('class' => 'calendar-controls'));
-                $content .= $prevlink . '<span class="hide"> | </span>';
-                $content .= \html_writer::tag('span', \html_writer::link($calendarlink,
-                    userdate($time, get_string('strftimemonthyear')), array('title' => get_string('monththis', 'calendar'))
-                    ), array('class' => 'current'));
-                $content .= '<span class="hide"> | </span>' . $right;
-                $content .= "<span class=\"clearer\"><!-- --></span>\n";
-                $content .= \html_writer::end_tag('div');
-
-                break;
-            case 'course':
-                $prevlink = self::get_link_previous(get_string('monthprev', 'access'), $urlbase, false, false, false,
-                    true, $prevmonthtime);
-                $nextlink = self::get_link_next(get_string('monthnext', 'access'), $urlbase, false, false, false,
-                    true, $nextmonthtime);
-                $calendarlink = self::get_link_href(new \moodle_url(CALENDAR_URL . 'view.php', array('view' => 'month')),
-                    false, false, false, $time);
-
-                if (!empty($data['id'])) {
-                    $calendarlink->param('course', $data['id']);
-                }
-
-                $content .= \html_writer::start_tag('div', array('class' => 'calendar-controls'));
-                $content .= $prevlink . '<span class="hide"> | </span>';
-                $content .= \html_writer::tag('span', \html_writer::link($calendarlink,
-                    userdate($time, get_string('strftimemonthyear')), array('title' => get_string('monththis', 'calendar'))
-                    ), array('class' => 'current'));
-                $content .= '<span class="hide"> | </span>' . $nextlink;
-                $content .= "<span class=\"clearer\"><!-- --></span>";
-                $content .= \html_writer::end_tag('div');
-                break;
-            case 'upcoming':
-                $calendarlink = self::get_link_href(new \moodle_url(CALENDAR_URL . 'view.php', array('view' => 'upcoming')),
-                    false, false, false, $time);
-                if (!empty($data['id'])) {
-                    $calendarlink->param('course', $data['id']);
-                }
-                $calendarlink = \html_writer::link($calendarlink, userdate($time, get_string('strftimemonthyear')));
-                $content .= \html_writer::tag('div', $calendarlink, array('class' => 'centered'));
-                break;
-            case 'display':
-                $calendarlink = self::get_link_href(new \moodle_url(CALENDAR_URL . 'view.php', array('view' => 'month')),
-                    false, false, false, $time);
-                if (!empty($data['id'])) {
-                    $calendarlink->param('course', $data['id']);
-                }
-                $calendarlink = \html_writer::link($calendarlink, userdate($time, get_string('strftimemonthyear')));
-                $content .= \html_writer::tag('h3', $calendarlink);
-                break;
-            case 'month':
-                $prevlink = self::get_link_previous(userdate($prevmonthtime, get_string('strftimemonthyear')),
-                    'view.php?view=month' . $courseid . '&amp;', false, false, false, false, $prevmonthtime);
-                $nextlink = self::get_link_next(userdate($nextmonthtime, get_string('strftimemonthyear')),
-                    'view.php?view=month' . $courseid . '&amp;', false, false, false, false, $nextmonthtime);
-
-                $content .= \html_writer::start_tag('div', array('class' => 'calendar-controls'));
-                $content .= $prevlink . '<span class="hide"> | </span>';
-                $content .= $OUTPUT->heading(userdate($time, get_string('strftimemonthyear')), 2, 'current');
-                $content .= '<span class="hide"> | </span>' . $nextlink;
-                $content .= '<span class="clearer"><!-- --></span>';
-                $content .= \html_writer::end_tag('div')."\n";
-                break;
-            case 'day':
-                $days = self::get_days();
-
-                $prevtimestamp = strtotime('-1 day', $time);
-                $nexttimestamp = strtotime('+1 day', $time);
-
-                $prevdate = $calendartype->timestamp_to_date_array($prevtimestamp);
-                $nextdate = $calendartype->timestamp_to_date_array($nexttimestamp);
-
-                $prevname = $days[$prevdate['wday']]['fullname'];
-                $nextname = $days[$nextdate['wday']]['fullname'];
-                $prevlink = self::get_link_previous($prevname, 'view.php?view=day' . $courseid . '&amp;', false, false,
-                    false, false, $prevtimestamp);
-                $nextlink = self::get_link_next($nextname, 'view.php?view=day' . $courseid . '&amp;', false, false, false,
-                    false, $nexttimestamp);
-
-                $content .= \html_writer::start_tag('div', array('class' => 'calendar-controls'));
-                $content .= $prevlink;
-                $content .= '<span class="hide"> | </span><span class="current">' .userdate($time,
-                        get_string('strftimedaydate')) . '</span>';
-                $content .= '<span class="hide"> | </span>' . $nextlink;
-                $content .= "<span class=\"clearer\"><!-- --></span>";
-                $content .= \html_writer::end_tag('div') . "\n";
-
-                break;
-        }
-
-        return $content;
-    }
-
-    /**
-     * Formats a filter control element.
-     *
-     * @param \moodle_url $url of the filter
-     * @param int $type constant defining the type filter
-     * @return string html content of the element
-     */
-    public static function get_filter_controls_element(\moodle_url $url, $type) {
-        global $OUTPUT;
-
-        switch ($type) {
-            case CALENDAR_EVENT_GLOBAL:
-                $typeforhumans = 'global';
-                $class = 'calendar_event_global';
-                break;
-            case CALENDAR_EVENT_COURSE:
-                $typeforhumans = 'course';
-                $class = 'calendar_event_course';
-                break;
-            case CALENDAR_EVENT_GROUP:
-                $typeforhumans = 'groups';
-                $class = 'calendar_event_group';
-                break;
-            case CALENDAR_EVENT_USER:
-                $typeforhumans = 'user';
-                $class = 'calendar_event_user';
-                break;
-        }
-
-        if (self::show_event_type($type)) {
-            $icon = $OUTPUT->pix_icon('t/hide', get_string('hide'));
-            $str = get_string('hide' . $typeforhumans . 'events', 'calendar');
-        } else {
-            $icon = $OUTPUT->pix_icon('t/show', get_string('show'));
-            $str = get_string('show' . $typeforhumans . 'events', 'calendar');
-        }
-        $content = \html_writer::start_tag('li', array('class' => 'calendar_event'));
-        $content .= \html_writer::start_tag('a', array('href' => $url, 'rel' => 'nofollow'));
-        $content .= \html_writer::tag('span', $icon, array('class' => $class));
-        $content .= \html_writer::tag('span', $str, array('class' => 'eventname'));
-        $content .= \html_writer::end_tag('a');
-        $content .= \html_writer::end_tag('li');
-
-        return $content;
-    }
-
-    /**
-     * Get the controls filter for calendar.
-     *
-     * Filter is used to hide calendar info from the display page
-     *
-     * @param \moodle_url $returnurl return-url for filter controls
-     * @return string $content return filter controls in html
-     */
-    public static function get_filter_controls(\moodle_url $returnurl) {
-        $groupevents = true;
-
-        $seturl = new \moodle_url('/calendar/set.php', array('return' => base64_encode($returnurl->out_as_local_url(false)),
-            'sesskey' => sesskey()));
-        $content = \html_writer::start_tag('ul');
-
-        $seturl->param('var', 'showglobal');
-        $content .= self::get_filter_controls_element($seturl, CALENDAR_EVENT_GLOBAL);
-
-        $seturl->param('var', 'showcourses');
-        $content .= self::get_filter_controls_element($seturl, CALENDAR_EVENT_COURSE);
-
-        if (isloggedin() && !isguestuser()) {
-            if ($groupevents) {
-                // This course MIGHT have group events defined, so show the filter.
-                $seturl->param('var', 'showgroups');
-                $content .= self::get_filter_controls_element($seturl, CALENDAR_EVENT_GROUP);
-            }
-            $seturl->param('var', 'showuser');
-            $content .= self::get_filter_controls_element($seturl, CALENDAR_EVENT_USER);
-        }
-        $content .= \html_writer::end_tag('ul');
-
-        return $content;
-    }
-
-    /**
-     * Return the representation day
-     *
-     * @param int $tstamp Timestamp in GMT
-     * @param int|bool $now current Unix timestamp
-     * @param bool $usecommonwords
-     * @return string the formatted date/time
-     */
-    public static function get_day_representation($tstamp, $now = false, $usecommonwords = true) {
-
-        static $shortformat;
-        if (empty($shortformat)) {
-            $shortformat = get_string('strftimedayshort');
-        }
-
-        if ($now === false) {
-            $now = time();
-        }
-
-        // To have it in one place, if a change is needed.
-        $formal = userdate($tstamp, $shortformat);
-
-        $datestamp = usergetdate($tstamp);
-        $datenow = usergetdate($now);
-
-        if ($usecommonwords == false) {
-            // We don't want words, just a date.
-            return $formal;
-        } else if ($datestamp['year'] == $datenow['year'] && $datestamp['yday'] == $datenow['yday']) {
-            return get_string('today', 'calendar');
-        } else if (($datestamp['year'] == $datenow['year'] && $datestamp['yday'] == $datenow['yday'] - 1 ) ||
-            ($datestamp['year'] == $datenow['year'] - 1 && $datestamp['mday'] == 31 && $datestamp['mon'] == 12
-                && $datenow['yday'] == 1)) {
-            return get_string('yesterday', 'calendar');
-        } else if (($datestamp['year'] == $datenow['year'] && $datestamp['yday'] == $datenow['yday'] + 1 ) ||
-            ($datestamp['year'] == $datenow['year'] + 1 && $datenow['mday'] == 31 && $datenow['mon'] == 12
-                && $datestamp['yday'] == 1)) {
-            return get_string('tomorrow', 'calendar');
-        } else {
-            return $formal;
-        }
-    }
-
-    /**
-     * return the formatted representation time
-     *
-     * @param int $time the timestamp in UTC, as obtained from the database
-     * @return string the formatted date/time
-     */
-    public static function get_time_representation($time) {
-        static $langtimeformat = null;
-
-        if ($langtimeformat === null) {
-            $langtimeformat = get_string('strftimetime');
-        }
-
-        $timeformat = get_user_preferences('calendar_timeformat');
-        if (empty($timeformat)) {
-            $timeformat = get_config(null, 'calendar_site_timeformat');
-        }
-
-        return userdate($time, empty($timeformat) ? $langtimeformat : $timeformat);
-    }
-
-    /**
-     * Adds day, month, year arguments to a URL and returns a moodle_url object.
-     *
-     * @param string|\moodle_url $linkbase
-     * @param int $d The number of the day.
-     * @param int $m The number of the month.
-     * @param int $y The number of the year.
-     * @param int $time the unixtime, used for multiple calendar support. The values $d,
-     *     $m and $y are kept for backwards compatibility.
-     * @return \moodle_url|null $linkbase
-     */
-    public static function get_link_href($linkbase, $d, $m, $y, $time = 0) {
-        if (empty($linkbase)) {
-            return null;
-        }
-
-        if (!($linkbase instanceof \moodle_url)) {
-            $linkbase = new \moodle_url($linkbase);
-        }
-
-        // If a day, month and year were passed then convert it to a timestamp. If these were passed
-        // then we can assume the day, month and year are passed as Gregorian, as no where in core
-        // should we be passing these values rather than the time.
-        if (!empty($d) && !empty($m) && !empty($y)) {
-            if (checkdate($m, $d, $y)) {
-                $time = make_timestamp($y, $m, $d);
-            } else {
-                $time = time();
-            }
-        } else if (empty($time)) {
-            $time = time();
-        }
-
-        $linkbase->param('time', $time);
-
-        return $linkbase;
-    }
-
-    /**
-     * Build and return a previous month HTML link, with an arrow.
-     *
-     * @param string $text The text label.
-     * @param string|\moodle_url $linkbase The URL stub.
-     * @param int $d The number of the date.
-     * @param int $m The number of the month.
-     * @param int $y year The number of the year.
-     * @param bool $accesshide Default visible, or hide from all except screenreaders.
-     * @param int $time the unixtime, used for multiple calendar support. The values $d,
-     *     $m and $y are kept for backwards compatibility.
-     * @return string HTML string.
-     */
-    public static function get_link_previous($text, $linkbase, $d, $m, $y, $accesshide = false, $time = 0) {
-        $href = self::get_link_href(new \moodle_url($linkbase), $d, $m, $y, $time);
-
-        if (empty($href)) {
-            return $text;
-        }
-
-        return link_arrow_left($text, (string)$href, $accesshide, 'previous');
-    }
-
-    /**
-     * Build and return a next month HTML link, with an arrow.
-     *
-     * @param string $text The text label.
-     * @param string|\moodle_url $linkbase The URL stub.
-     * @param int $d the number of the Day
-     * @param int $m The number of the month.
-     * @param int $y The number of the year.
-     * @param bool $accesshide Default visible, or hide from all except screenreaders.
-     * @param int $time the unixtime, used for multiple calendar support. The values $d,
-     *     $m and $y are kept for backwards compatibility.
-     * @return string HTML string.
-     */
-    public static function get_link_next($text, $linkbase, $d, $m, $y, $accesshide = false, $time = 0) {
-        $href = self::get_link_href(new \moodle_url($linkbase), $d, $m, $y, $time);
-
-        if (empty($href)) {
-            return $text;
-        }
-
-        return link_arrow_right($text, (string)$href, $accesshide, 'next');
-    }
-
-    /**
-     * Return the number of days in month
-     *
-     * @param int $month the number of the month.
-     * @param int $year the number of the year
-     * @return int
-     */
-    public static function get_days_in_month($month, $year) {
-        $calendartype = type_factory::get_calendar_instance();
-        return $calendartype->get_num_days_in_month($year, $month);
-    }
-
-    /**
-     * Get the next following month
-     *
-     * @param int $month the number of the month.
-     * @param int $year the number of the year.
-     * @return array the following month
-     */
-    public static function get_next_month($month, $year) {
-        $calendartype = type_factory::get_calendar_instance();
-        return $calendartype->get_next_month($year, $month);
-    }
-
-    /**
-     * Get the previous month.
-     *
-     * @param int $month the number of the month.
-     * @param int $year the number of the year.
-     * @return array previous month
-     */
-    public static function get_prev_month($month, $year) {
-        $calendartype = type_factory::get_calendar_instance();
-        return $calendartype->get_prev_month($year, $month);
-    }
-
-    /**
-     * Get per-day basis events.
-     *
-     * @param array $events list of events
-     * @param int $month the number of the month
-     * @param int $year the number of the year
-     * @param array $eventsbyday event on specific day
-     * @param array $durationbyday duration of the event in days
-     * @param array $typesbyday event type (eg: global, course, user, or group)
-     * @param array $courses list of courses
-     * @return void
-     */
-    public static function get_events_by_day($events, $month, $year, &$eventsbyday, &$durationbyday, &$typesbyday, &$courses) {
-        $calendartype = type_factory::get_calendar_instance();
-
-        $eventsbyday = array();
-        $typesbyday = array();
-        $durationbyday = array();
-
-        if ($events === false) {
-            return;
-        }
-
-        foreach ($events as $event) {
-            $startdate = $calendartype->timestamp_to_date_array($event->timestart);
-            if ($event->timeduration) {
-                $enddate = $calendartype->timestamp_to_date_array($event->timestart + $event->timeduration - 1);
-            } else {
-                $enddate = $startdate;
-            }
-
-            // Simple arithmetic: $year * 13 + $month is a distinct integer for each distinct ($year, $month) pair.
-            if (!($startdate['year'] * 13 + $startdate['mon'] <= $year * 13 + $month) &&
-                ($enddate['year'] * 13 + $enddate['mon'] >= $year * 13 + $month)) {
-                continue;
-            }
-
-            $eventdaystart = intval($startdate['mday']);
-
-            if ($startdate['mon'] == $month && $startdate['year'] == $year) {
-                // Give the event to its day.
-                $eventsbyday[$eventdaystart][] = $event->id;
-
-                // Mark the day as having such an event.
-                if ($event->courseid == SITEID && $event->groupid == 0) {
-                    $typesbyday[$eventdaystart]['startglobal'] = true;
-                    // Set event class for global event.
-                    $events[$event->id]->class = 'calendar_event_global';
-                } else if ($event->courseid != 0 && $event->courseid != SITEID && $event->groupid == 0) {
-                    $typesbyday[$eventdaystart]['startcourse'] = true;
-                    // Set event class for course event.
-                    $events[$event->id]->class = 'calendar_event_course';
-                } else if ($event->groupid) {
-                    $typesbyday[$eventdaystart]['startgroup'] = true;
-                    // Set event class for group event.
-                    $events[$event->id]->class = 'calendar_event_group';
-                } else if ($event->userid) {
-                    $typesbyday[$eventdaystart]['startuser'] = true;
-                    // Set event class for user event.
-                    $events[$event->id]->class = 'calendar_event_user';
-                }
-            }
-
-            if ($event->timeduration == 0) {
-                // Proceed with the next.
-                continue;
-            }
-
-            // The event starts on $month $year or before.
-            if ($startdate['mon'] == $month && $startdate['year'] == $year) {
-                $lowerbound = intval($startdate['mday']);
-            } else {
-                $lowerbound = 0;
-            }
-
-            // Also, it ends on $month $year or later.
-            if ($enddate['mon'] == $month && $enddate['year'] == $year) {
-                $upperbound = intval($enddate['mday']);
-            } else {
-                $upperbound = self::get_days_in_month($month, $year);
-            }
-
-            // Mark all days between $lowerbound and $upperbound (inclusive) as duration.
-            for ($i = $lowerbound + 1; $i <= $upperbound; ++$i) {
-                $durationbyday[$i][] = $event->id;
-                if ($event->courseid == SITEID && $event->groupid == 0) {
-                    $typesbyday[$i]['durationglobal'] = true;
-                } else if ($event->courseid != 0 && $event->courseid != SITEID && $event->groupid == 0) {
-                    $typesbyday[$i]['durationcourse'] = true;
-                } else if ($event->groupid) {
-                    $typesbyday[$i]['durationgroup'] = true;
-                } else if ($event->userid) {
-                    $typesbyday[$i]['durationuser'] = true;
-                }
-            }
-
-        }
-        return;
-    }
-
-    /**
-     * Returns the courses to load events for, the
-     *
-     * @param array $courseeventsfrom An array of courses to load calendar events for
-     * @param bool $ignorefilters specify the use of filters, false is set as default
-     * @return array An array of courses, groups, and user to load calendar events for based upon filters
-     */
-    public static function set_filters(array $courseeventsfrom, $ignorefilters = false) {
-        global $USER, $CFG;
-
-        // For backwards compatability we have to check whether the courses array contains
-        // just id's in which case we need to load course objects.
-        $coursestoload = array();
-        foreach ($courseeventsfrom as $id => $something) {
-            if (!is_object($something)) {
-                $coursestoload[] = $id;
-                unset($courseeventsfrom[$id]);
-            }
-        }
-
-        $courses = array();
-        $user = false;
-        $group = false;
-
-        // Get the capabilities that allow seeing group events from all groups.
-        $allgroupscaps = array('moodle/site:accessallgroups', 'moodle/calendar:manageentries');
-
-        $isloggedin = isloggedin();
-
-        if ($ignorefilters || self::show_event_type(CALENDAR_EVENT_COURSE)) {
-            $courses = array_keys($courseeventsfrom);
-        }
-        if ($ignorefilters || self::show_event_type(CALENDAR_EVENT_GLOBAL)) {
-            $courses[] = SITEID;
-        }
-        $courses = array_unique($courses);
-        sort($courses);
-
-        if (!empty($courses) && in_array(SITEID, $courses)) {
-            // Sort courses for consistent colour highlighting.
-            // Effectively ignoring SITEID as setting as last course id.
-            $key = array_search(SITEID, $courses);
-            unset($courses[$key]);
-            $courses[] = SITEID;
-        }
-
-        if ($ignorefilters || ($isloggedin && self::show_event_type(CALENDAR_EVENT_USER))) {
-            $user = $USER->id;
-        }
-
-        if (!empty($courseeventsfrom) && (self::show_event_type(CALENDAR_EVENT_GROUP) || $ignorefilters)) {
-
-            if (count($courseeventsfrom) == 1) {
-                $course = reset($courseeventsfrom);
-                if (has_any_capability($allgroupscaps, \context_course::instance($course->id))) {
-                    $coursegroups = groups_get_all_groups($course->id, 0, 0, 'g.id');
-                    $group = array_keys($coursegroups);
-                }
-            }
-            if ($group === false) {
-                if (!empty($CFG->calendar_adminseesall) && has_any_capability($allgroupscaps, \context_system::instance())) {
-                    $group = true;
-                } else if ($isloggedin) {
-                    $groupids = array();
-                    foreach ($courseeventsfrom as $courseid => $course) {
-                        // If the user is an editing teacher in there.
-                        if (!empty($USER->groupmember[$course->id])) {
-                            // We've already cached the users groups for this course so we can just use that.
-                            $groupids = array_merge($groupids, $USER->groupmember[$course->id]);
-                        } else if ($course->groupmode != NOGROUPS || !$course->groupmodeforce) {
-                            // If this course has groups, show events from all of those related to the current user.
-                            $coursegroups = groups_get_user_groups($course->id, $USER->id);
-                            $groupids = array_merge($groupids, $coursegroups['0']);
-                        }
-                    }
-                    if (!empty($groupids)) {
-                        $group = $groupids;
-                    }
-                }
-            }
-        }
-        if (empty($courses)) {
-            $courses = false;
-        }
-
-        return array($courses, $group, $user);
-    }
-
-    /**
-     * Return the capability for editing calendar event
-     *
-     * @param \calendar_event $event event object
-     * @return bool capability to edit event
-     */
-    public static function can_edit_event($event) {
-        global $USER, $DB;
-
-        // Must be logged in.
-        if (!isloggedin()) {
-            return false;
-        }
-
-        // Can not be using guest account.
-        if (isguestuser()) {
-            return false;
-        }
-
-        // You cannot edit calendar subscription events presently.
-        if (!empty($event->subscriptionid)) {
-            if (!empty($event->subscription->url)) {
-                // This event can be updated externally, so it cannot be edited.
-                return false;
-            }
-        }
-
-        $sitecontext = \context_system::instance();
-
-        // If user has manageentries at site level, return true.
-        if (has_capability('moodle/calendar:manageentries', $sitecontext)) {
-            return true;
-        }
-
-        // If groupid is set, it's definitely a group event.
-        if (!empty($event->groupid)) {
-            // Allow users to add/edit group events if -
-            // 1) They have manageentries for the course OR
-            // 2) They have managegroupentries AND are in the group.
-            $group = $DB->get_record('groups', array('id' => $event->groupid));
-            return $group && (
-                    has_capability('moodle/calendar:manageentries', $event->context) ||
-                    (has_capability('moodle/calendar:managegroupentries', $event->context)
-                        && groups_is_member($event->groupid)));
-        } else if (!empty($event->courseid)) {
-            // If groupid is not set, but course is set, it's definiely a course event.
-            return has_capability('moodle/calendar:manageentries', $event->context);
-        } else if (!empty($event->userid) && $event->userid == $USER->id) {
-            // If course is not set, but userid id set, it's a user event.
-            return (has_capability('moodle/calendar:manageownentries', $event->context));
-        } else if (!empty($event->userid)) {
-            return (has_capability('moodle/calendar:manageentries', $event->context));
-        }
-
-        return false;
-    }
-
-    /**
-     * Returns the default courses to display on the calendar when there isn't a specific
-     * course to display.
-     *
-     * @return array $courses Array of courses to display
-     */
-    public static function get_default_courses() {
-        global $CFG, $DB;
-
-        if (!isloggedin()) {
-            return array();
-        }
-
-        if (!empty($CFG->calendar_adminseesall) && has_capability('moodle/calendar:manageentries', \context_system::instance())) {
-            $select = ', ' . \context_helper::get_preload_record_columns_sql('ctx');
-            $join = "LEFT JOIN {context} ctx ON (ctx.instanceid = c.id AND ctx.contextlevel = :contextlevel)";
-            $sql = "SELECT c.* $select
-                      FROM {course} c
-                      $join
-                     WHERE EXISTS (SELECT 1 FROM {event} e WHERE e.courseid = c.id)
-                  ";
-            $courses = $DB->get_records_sql($sql, array('contextlevel' => CONTEXT_COURSE), 0, 20);
-            foreach ($courses as $course) {
-                \context_helper::preload_from_record($course);
-            }
-            return $courses;
-        }
-
-        $courses = enrol_get_my_courses();
-
-        return $courses;
-    }
-
-    /**
-     * Get event format time
-     *
-     * @param \calendar_event $event event object
-     * @param int $now current time in gmt
-     * @param array $linkparams list of params for event link
-     * @param bool $usecommonwords the words as formatted date/time.
-     * @param int $showtime determine the show time GMT timestamp
-     * @return string $eventtime link/string for event time
-     */
-    public static function get_format_event_time($event, $now, $linkparams = null, $usecommonwords = true, $showtime = 0) {
-        $starttime = $event->timestart;
-        $endtime = $event->timestart + $event->timeduration;
-
-        if (empty($linkparams) || !is_array($linkparams)) {
-            $linkparams = array();
-        }
-
-        $linkparams['view'] = 'day';
-
-        // OK, now to get a meaningful display.
-        // Check if there is a duration for this event.
-        if ($event->timeduration) {
-            // Get the midnight of the day the event will start.
-            $usermidnightstart = usergetmidnight($starttime);
-            // Get the midnight of the day the event will end.
-            $usermidnightend = usergetmidnight($endtime);
-            // Check if we will still be on the same day.
-            if ($usermidnightstart == $usermidnightend) {
-                // Check if we are running all day.
-                if ($event->timeduration == DAYSECS) {
-                    $time = get_string('allday', 'calendar');
-                } else { // Specify the time we will be running this from.
-                    $datestart = self::get_time_representation($starttime);
-                    $dateend = self::get_time_representation($endtime);
-                    $time = $datestart . ' <strong>&raquo;</strong> ' . $dateend;
-                }
-
-                // Set printable representation.
-                if (!$showtime) {
-                    $day = self::get_day_representation($event->timestart, $now, $usecommonwords);
-                    $url = self::get_link_href(new \moodle_url(CALENDAR_URL . 'view.php', $linkparams), 0, 0, 0, $endtime);
-                    $eventtime = \html_writer::link($url, $day) . ', ' . $time;
-                } else {
-                    $eventtime = $time;
-                }
-            } else { // It must spans two or more days.
-                $daystart = self::get_day_representation($event->timestart, $now, $usecommonwords) . ', ';
-                if ($showtime == $usermidnightstart) {
-                    $daystart = '';
-                }
-                $timestart = self::get_time_representation($event->timestart);
-                $dayend = self::get_day_representation($event->timestart + $event->timeduration, $now, $usecommonwords) . ', ';
-                if ($showtime == $usermidnightend) {
-                    $dayend = '';
-                }
-                $timeend = self::get_time_representation($event->timestart + $event->timeduration);
-
-                // Set printable representation.
-                if ($now >= $usermidnightstart && $now < strtotime('+1 day', $usermidnightstart)) {
-                    $url = self::get_link_href(new \moodle_url(CALENDAR_URL . 'view.php', $linkparams), 0, 0, 0, $endtime);
-                    $eventtime = $timestart . ' <strong>&raquo;</strong> ' . \html_writer::link($url, $dayend) . $timeend;
-                } else {
-                    // The event is in the future, print start and end links.
-                    $url = self::get_link_href(new \moodle_url(CALENDAR_URL . 'view.php', $linkparams), 0, 0, 0, $starttime);
-                    $eventtime = \html_writer::link($url, $daystart) . $timestart . ' <strong>&raquo;</strong> ';
-
-                    $url = self::get_link_href(new \moodle_url(CALENDAR_URL . 'view.php', $linkparams),  0, 0, 0, $endtime);
-                    $eventtime .= \html_writer::link($url, $dayend) . $timeend;
-                }
-            }
-        } else { // There is no time duration.
-            $time = self::get_time_representation($event->timestart);
-            // Set printable representation.
-            if (!$showtime) {
-                $day = self::get_day_representation($event->timestart, $now, $usecommonwords);
-                $url = self::get_link_href(new \moodle_url(CALENDAR_URL . 'view.php', $linkparams),  0, 0, 0, $starttime);
-                $eventtime = \html_writer::link($url, $day) . ', ' . trim($time);
-            } else {
-                $eventtime = $time;
-            }
-        }
-
-        // Check if It has expired.
-        if ($event->timestart + $event->timeduration < $now) {
-            $eventtime = '<span class="dimmed_text">' . str_replace(' href=', ' class="dimmed" href=', $eventtime) . '</span>';
-        }
-
-        return $eventtime;
-    }
-
-    /**
-     * Checks to see if the requested type of event should be shown for the given user.
-     *
-     * @param int $type The type to check the display for (default is to display all)
-     * @param \stdClass|int|null $user The user to check for - by default the current user
-     * @return bool True if the tyep should be displayed false otherwise
-     */
-    public static function show_event_type($type, $user = null) {
-        $default = CALENDAR_EVENT_GLOBAL + CALENDAR_EVENT_COURSE + CALENDAR_EVENT_GROUP + CALENDAR_EVENT_USER;
-
-        if (get_user_preferences('calendar_persistflt', 0, $user) === 0) {
-            global $SESSION;
-            if (!isset($SESSION->calendarshoweventtype)) {
-                $SESSION->calendarshoweventtype = $default;
-            }
-            return $SESSION->calendarshoweventtype & $type;
-        } else {
-            return get_user_preferences('calendar_savedflt', $default, $user) & $type;
-        }
-    }
-
-    /**
-     * Sets the display of the event type given $display.
-     *
-     * If $display = true the event type will be shown.
-     * If $display = false the event type will NOT be shown.
-     * If $display = null the current value will be toggled and saved.
-     *
-     * @param int $type object of CALENDAR_EVENT_XXX
-     * @param bool $display option to display event type
-     * @param \stdClass|int $user moodle user object or id, null means current user
-     */
-    public static function set_event_type_display($type, $display = null, $user = null) {
-        $persist = get_user_preferences('calendar_persistflt', 0, $user);
-        $default = CALENDAR_EVENT_GLOBAL + CALENDAR_EVENT_COURSE + CALENDAR_EVENT_GROUP + CALENDAR_EVENT_USER;
-        if ($persist === 0) {
-            global $SESSION;
-            if (!isset($SESSION->calendarshoweventtype)) {
-                $SESSION->calendarshoweventtype = $default;
-            }
-            $preference = $SESSION->calendarshoweventtype;
-        } else {
-            $preference = get_user_preferences('calendar_savedflt', $default, $user);
-        }
-        $current = $preference & $type;
-        if ($display === null) {
-            $display = !$current;
-        }
-        if ($display && !$current) {
-            $preference += $type;
-        } else if (!$display && $current) {
-            $preference -= $type;
-        }
-        if ($persist === 0) {
-            $SESSION->calendarshoweventtype = $preference;
-        } else {
-            if ($preference == $default) {
-                unset_user_preference('calendar_savedflt', $user);
-            } else {
-                set_user_preference('calendar_savedflt', $preference, $user);
-            }
-        }
-    }
-
-    /**
-     * Get calendar's allowed types
-     *
-     * @param \stdClass $allowed list of allowed edit for event  type
-     * @param \stdClass|int $course object of a course or course id
-     */
-    public static function get_allowed_types(&$allowed, $course = null) {
-        global $USER, $DB;
-
-        $allowed = new \stdClass();
-        $allowed->user = has_capability('moodle/calendar:manageownentries', \context_system::instance());
-        $allowed->groups = false;
-        $allowed->courses = false;
-        $allowed->site = has_capability('moodle/calendar:manageentries', \context_course::instance(SITEID));
-
-        if (!empty($course)) {
-            if (!is_object($course)) {
-                $course = $DB->get_record('course', array('id' => $course), '*', MUST_EXIST);
-            }
-            if ($course->id != SITEID) {
-                $coursecontext = \context_course::instance($course->id);
-                $allowed->user = has_capability('moodle/calendar:manageownentries', $coursecontext);
-
-                if (has_capability('moodle/calendar:manageentries', $coursecontext)) {
-                    $allowed->courses = array($course->id => 1);
-
-                    if ($course->groupmode != NOGROUPS || !$course->groupmodeforce) {
-                        if (has_capability('moodle/site:accessallgroups', $coursecontext)) {
-                            $allowed->groups = groups_get_all_groups($course->id);
-                        } else {
-                            $allowed->groups = groups_get_all_groups($course->id, $USER->id);
-                        }
-                    }
-                } else if (has_capability('moodle/calendar:managegroupentries', $coursecontext)) {
-                    if ($course->groupmode != NOGROUPS || !$course->groupmodeforce) {
-                        if (has_capability('moodle/site:accessallgroups', $coursecontext)) {
-                            $allowed->groups = groups_get_all_groups($course->id);
-                        } else {
-                            $allowed->groups = groups_get_all_groups($course->id, $USER->id);
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * See if user can add calendar entries at all
-     * used to print the "New Event" button
-     *
-     * @param \stdClass $course object of a course or course id
-     * @return bool has the capability to add at least one event type
-     */
-    public static function can_add_event_to_course($course) {
-        if (!isloggedin() || isguestuser()) {
-            return false;
-        }
-
-        self::get_allowed_types($allowed, $course);
-
-        return (bool)($allowed->user || $allowed->groups || $allowed->courses || $allowed->site);
-    }
-
-    /**
-     * Check wether the current user is permitted to add events
-     *
-     * @param \stdClass $event object of event
-     * @return bool has the capability to add event
-     */
-    public static function can_add_event($event) {
-        global $USER, $DB;
-
-        // Can not be using guest account.
-        if (!isloggedin() or isguestuser()) {
-            return false;
-        }
-
-        $sitecontext = \context_system::instance();
-
-        // If user has manageentries at site level, always return true.
-        if (has_capability('moodle/calendar:manageentries', $sitecontext)) {
-            return true;
-        }
-
-        switch ($event->eventtype) {
-            case 'course':
-                return has_capability('moodle/calendar:manageentries', $event->context);
-            case 'group':
-                // Allow users to add/edit group events if -
-                // 1) They have manageentries (= entries for whole course).
-                // 2) They have managegroupentries AND are in the group.
-                $group = $DB->get_record('groups', array('id' => $event->groupid));
-                return $group && (
-                        has_capability('moodle/calendar:manageentries', $event->context) ||
-                        (has_capability('moodle/calendar:managegroupentries', $event->context)
-                            && groups_is_member($event->groupid)));
-            case 'user':
-                if ($event->userid == $USER->id) {
-                    return (has_capability('moodle/calendar:manageownentries', $event->context));
-                }
-                // There is intentionally no 'break'.
-            case 'site':
-                return has_capability('moodle/calendar:manageentries', $event->context);
-            default:
-                return has_capability('moodle/calendar:manageentries', $event->context);
-        }
-    }
-
-    /**
-     * Returns option list for the poll interval setting.
-     *
-     * @return array An array of poll interval options. Interval => description.
-     */
-    public static function get_poll_interval_choices() {
-        return array(
-            '0' => new \lang_string('never', 'calendar'),
-            HOURSECS => new \lang_string('hourly', 'calendar'),
-            DAYSECS => new \lang_string('daily', 'calendar'),
-            WEEKSECS => new \lang_string('weekly', 'calendar'),
-            '2628000' => new \lang_string('monthly', 'calendar'),
-            YEARSECS => new \lang_string('annually', 'calendar')
-        );
-    }
-
-    /**
-     * Returns option list of available options for the calendar event type, given the current user and course.
-     *
-     * @param int $courseid The id of the course
-     * @return array An array containing the event types the user can create.
-     */
-    public static function get_event_type_choices($courseid) {
-        $choices = array();
-        $allowed = new \stdClass;
-        self::get_allowed_types($allowed, $courseid);
-
-        if ($allowed->user) {
-            $choices['user'] = get_string('userevents', 'calendar');
-        }
-        if ($allowed->site) {
-            $choices['site'] = get_string('siteevents', 'calendar');
-        }
-        if (!empty($allowed->courses)) {
-            $choices['course'] = get_string('courseevents', 'calendar');
-        }
-        if (!empty($allowed->groups) and is_array($allowed->groups)) {
-            $choices['group'] = get_string('group');
-        }
-
-        return array($choices, $allowed->groups);
-    }
-
-    /**
-     * Add an iCalendar subscription to the database.
-     *
-     * @param \stdClass $sub The subscription object (e.g. from the form)
-     * @return int The insert ID, if any.
-     */
-    public static function add_subscription($sub) {
-        global $DB, $USER, $SITE;
-
-        if ($sub->eventtype === 'site') {
-            $sub->courseid = $SITE->id;
-        } else if ($sub->eventtype === 'group' || $sub->eventtype === 'course') {
-            $sub->courseid = $sub->course;
-        } else {
-            // User events.
-            $sub->courseid = 0;
-        }
-        $sub->userid = $USER->id;
-
-        // File subscriptions never update.
-        if (empty($sub->url)) {
-            $sub->pollinterval = 0;
-        }
-
-        if (!empty($sub->name)) {
-            if (empty($sub->id)) {
-                $id = $DB->insert_record('event_subscriptions', $sub);
-                // We cannot cache the data here because $sub is not complete.
-                $sub->id = $id;
-                // Trigger event, calendar subscription added.
-                $eventparams = array('objectid' => $sub->id,
-                    'context' => self::get_calendar_context($sub),
-                    'other' => array('eventtype' => $sub->eventtype, 'courseid' => $sub->courseid)
-                );
-                $event = \core\event\calendar_subscription_created::create($eventparams);
-                $event->trigger();
-                return $id;
-            } else {
-                // Why are we doing an update here?
-                self::update_subscription($sub);
-                return $sub->id;
-            }
-        } else {
-            print_error('errorbadsubscription', 'importcalendar');
-        }
-    }
-
-    /**
-     * Add an iCalendar event to the Moodle calendar.
-     *
-     * @param \stdClass $event The RFC-2445 iCalendar event
-     * @param int $courseid The course ID
-     * @param int $subscriptionid The iCalendar subscription ID
-     * @param string $timezone The X-WR-TIMEZONE iCalendar property if provided
-     * @return int Code: CALENDAR_IMPORT_EVENT_UPDATED = updated,  CALENDAR_IMPORT_EVENT_INSERTED = inserted, 0 = error
-     */
-    public static function add_icalendar_event($event, $courseid, $subscriptionid, $timezone='UTC') {
-        global $DB;
-
-        // Probably an unsupported X-MICROSOFT-CDO-BUSYSTATUS event.
-        if (empty($event->properties['SUMMARY'])) {
-            return 0;
-        }
-
-        $name = $event->properties['SUMMARY'][0]->value;
-        $name = str_replace('\n', '<br />', $name);
-        $name = str_replace('\\', '', $name);
-        $name = preg_replace('/\s+/u', ' ', $name);
-
-        $eventrecord = new \stdClass;
-        $eventrecord->name = clean_param($name, PARAM_NOTAGS);
-
-        if (empty($event->properties['DESCRIPTION'][0]->value)) {
-            $description = '';
-        } else {
-            $description = $event->properties['DESCRIPTION'][0]->value;
-            $description = clean_param($description, PARAM_NOTAGS);
-            $description = str_replace('\n', '<br />', $description);
-            $description = str_replace('\\', '', $description);
-            $description = preg_replace('/\s+/u', ' ', $description);
-        }
-        $eventrecord->description = $description;
-
-        // Probably a repeating event with RRULE etc. TODO: skip for now.
-        if (empty($event->properties['DTSTART'][0]->value)) {
-            return 0;
-        }
-
-        if (isset($event->properties['DTSTART'][0]->parameters['TZID'])) {
-            $tz = $event->properties['DTSTART'][0]->parameters['TZID'];
-        } else {
-            $tz = $timezone;
-        }
-        $tz = \core_date::normalise_timezone($tz);
-        $eventrecord->timestart = strtotime($event->properties['DTSTART'][0]->value . ' ' . $tz);
-        if (empty($event->properties['DTEND'])) {
-            $eventrecord->timeduration = 0; // No duration if no end time specified.
-        } else {
-            if (isset($event->properties['DTEND'][0]->parameters['TZID'])) {
-                $endtz = $event->properties['DTEND'][0]->parameters['TZID'];
-            } else {
-                $endtz = $timezone;
-            }
-            $endtz = \core_date::normalise_timezone($endtz);
-            $eventrecord->timeduration = strtotime($event->properties['DTEND'][0]->value . ' ' . $endtz) - $eventrecord->timestart;
-        }
-
-        // Check to see if it should be treated as an all day event.
-        if ($eventrecord->timeduration == DAYSECS) {
-            // Check to see if the event started at Midnight on the imported calendar.
-            date_default_timezone_set($timezone);
-            if (date('H:i:s', $eventrecord->timestart) === "00:00:00") {
-                // This event should be an all day event.
-                $eventrecord->timeduration = 0;
-            }
-            \core_date::set_default_server_timezone();
-        }
-
-        $eventrecord->uuid = $event->properties['UID'][0]->value;
-        $eventrecord->timemodified = time();
-
-        // Add the iCal subscription details if required.
-        // We should never do anything with an event without a subscription reference.
-        $sub = self::get_subscription($subscriptionid);
-        $eventrecord->subscriptionid = $subscriptionid;
-        $eventrecord->userid = $sub->userid;
-        $eventrecord->groupid = $sub->groupid;
-        $eventrecord->courseid = $sub->courseid;
-        $eventrecord->eventtype = $sub->eventtype;
-
-        if ($updaterecord = $DB->get_record('event', array('uuid' => $eventrecord->uuid,
-            'subscriptionid' => $eventrecord->subscriptionid))) {
-            $eventrecord->id = $updaterecord->id;
-            $return = CALENDAR_IMPORT_EVENT_UPDATED; // Update.
-        } else {
-            $return = CALENDAR_IMPORT_EVENT_INSERTED; // Insert.
-        }
-        if ($createdevent = \calendar_event::create($eventrecord, false)) {
-            if (!empty($event->properties['RRULE'])) {
-                // Repeating events.
-                date_default_timezone_set($tz); // Change time zone to parse all events.
-                $rrule = new rrule_manager($event->properties['RRULE'][0]->value);
-                $rrule->parse_rrule();
-                $rrule->create_events($createdevent);
-                \core_date::set_default_server_timezone(); // Change time zone back to what it was.
-            }
-            return $return;
-        } else {
-            return 0;
-        }
-    }
-
-    /**
-     * Update a subscription from the form data in one of the rows in the existing subscriptions table.
-     *
-     * @param int $subscriptionid The ID of the subscription we are acting upon.
-     * @param int $pollinterval The poll interval to use.
-     * @param int $action The action to be performed. One of update or remove.
-     * @return string A log of the import progress, including errors
-     */
-    public static function process_subscription_row($subscriptionid, $pollinterval, $action) {
-        // Fetch the subscription from the database making sure it exists.
-        $sub = self::get_subscription($subscriptionid);
-
-        // Update or remove the subscription, based on action.
-        switch ($action) {
-            case CALENDAR_SUBSCRIPTION_UPDATE:
-                // Skip updating file subscriptions.
-                if (empty($sub->url)) {
-                    break;
-                }
-                $sub->pollinterval = $pollinterval;
-                self::update_subscription($sub);
-
-                // Update the events.
-                return "<p>" . get_string('subscriptionupdated', 'calendar', $sub->name) . "</p>" .
-                    self::update_subscription_events($subscriptionid);
-            case CALENDAR_SUBSCRIPTION_REMOVE:
-                self::delete_subscription($subscriptionid);
-                return get_string('subscriptionremoved', 'calendar', $sub->name);
-                break;
-            default:
-                break;
-        }
-        return '';
-    }
-
-    /**
-     * Delete subscription and all related events.
-     *
-     * @param int|\stdClass $subscription subscription or it's id, which needs to be deleted.
-     */
-    public static function delete_subscription($subscription) {
-        global $DB;
-
-        if (!is_object($subscription)) {
-            $subscription = $DB->get_record('event_subscriptions', array('id' => $subscription), '*', MUST_EXIST);
-        }
-
-        // Delete subscription and related events.
-        $DB->delete_records('event', array('subscriptionid' => $subscription->id));
-        $DB->delete_records('event_subscriptions', array('id' => $subscription->id));
-        \cache_helper::invalidate_by_definition('core', 'calendar_subscriptions', array(), array($subscription->id));
-
-        // Trigger event, calendar subscription deleted.
-        $eventparams = array('objectid' => $subscription->id,
-            'context' => self::get_calendar_context($subscription),
-            'other' => array('courseid' => $subscription->courseid)
-        );
-        $event = \core\event\calendar_subscription_deleted::create($eventparams);
-        $event->trigger();
-    }
-
-    /**
-     * From a URL, fetch the calendar and return an iCalendar object.
-     *
-     * @param string $url The iCalendar URL
-     * @return \iCalendar The iCalendar object
-     * @throws \moodle_exception
-     */
-    public static function get_icalendar($url) {
-        global $CFG;
-
-        require_once($CFG->libdir . '/filelib.php');
-
-        $curl = new \curl();
-        $curl->setopt(array('CURLOPT_FOLLOWLOCATION' => 1, 'CURLOPT_MAXREDIRS' => 5));
-        $calendar = $curl->get($url);
-
-        // Http code validation should actually be the job of curl class.
-        if (!$calendar || $curl->info['http_code'] != 200 || !empty($curl->errorno)) {
-            throw new \moodle_exception('errorinvalidicalurl', 'calendar');
-        }
-
-        $ical = new \iCalendar();
-        $ical->unserialize($calendar);
-
-        return $ical;
-    }
-
-    /**
-     * Import events from an iCalendar object into a course calendar.
-     *
-     * @param \iCalendar $ical The iCalendar object.
-     * @param int $courseid The course ID for the calendar.
-     * @param int $subscriptionid The subscription ID.
-     * @return string A log of the import progress, including errors.
-     */
-    public static function import_icalendar_events($ical, $courseid, $subscriptionid = null) {
-        global $DB;
-
-        $return = '';
-        $eventcount = 0;
-        $updatecount = 0;
-
-        // Large calendars take a while...
-        if (!CLI_SCRIPT) {
-            \core_php_time_limit::raise(300);
-        }
-
-        // Mark all events in a subscription with a zero timestamp.
-        if (!empty($subscriptionid)) {
-            $sql = "UPDATE {event} SET timemodified = :time WHERE subscriptionid = :id";
-            $DB->execute($sql, array('time' => 0, 'id' => $subscriptionid));
-        }
-
-        // Grab the timezone from the iCalendar file to be used later.
-        if (isset($ical->properties['X-WR-TIMEZONE'][0]->value)) {
-            $timezone = $ical->properties['X-WR-TIMEZONE'][0]->value;
-        } else {
-            $timezone = 'UTC';
-        }
-
-        $return = '';
-        foreach ($ical->components['VEVENT'] as $event) {
-            $res = self::add_icalendar_event($event, $courseid, $subscriptionid, $timezone);
-            switch ($res) {
-                case CALENDAR_IMPORT_EVENT_UPDATED:
-                    $updatecount++;
-                    break;
-                case CALENDAR_IMPORT_EVENT_INSERTED:
-                    $eventcount++;
-                    break;
-                case 0:
-                    $return .= '<p>' . get_string('erroraddingevent', 'calendar') . ': ';
-                    if (empty($event->properties['SUMMARY'])) {
-                        $return .= '(' . get_string('notitle', 'calendar') . ')';
-                    } else {
-                        $return .= $event->properties['SUMMARY'][0]->value;
-                    }
-                    $return .= "</p>\n";
-                    break;
-            }
-        }
-
-        $return .= "<p>" . get_string('eventsimported', 'calendar', $eventcount) . "</p> ";
-        $return .= "<p>" . get_string('eventsupdated', 'calendar', $updatecount) . "</p>";
-
-        // Delete remaining zero-marked events since they're not in remote calendar.
-        if (!empty($subscriptionid)) {
-            $deletecount = $DB->count_records('event', array('timemodified' => 0, 'subscriptionid' => $subscriptionid));
-            if (!empty($deletecount)) {
-                $DB->delete_records('event', array('timemodified' => 0, 'subscriptionid' => $subscriptionid));
-                $return .= "<p> " . get_string('eventsdeleted', 'calendar') . ": {$deletecount} </p>\n";
-            }
-        }
-
-        return $return;
-    }
-
-    /**
-     * Fetch a calendar subscription and update the events in the calendar.
-     *
-     * @param int $subscriptionid The course ID for the calendar.
-     * @return string A log of the import progress, including errors.
-     */
-    public static function update_subscription_events($subscriptionid) {
-        $sub = self::get_subscription($subscriptionid);
-
-        // Don't update a file subscription.
-        if (empty($sub->url)) {
-            return 'File subscription not updated.';
-        }
-
-        $ical = self::get_icalendar($sub->url);
-        $return = self::import_icalendar_events($ical, $sub->courseid, $subscriptionid);
-        $sub->lastupdated = time();
-
-        self::update_subscription($sub);
-
-        return $return;
-    }
-
-    /**
-     * Update a calendar subscription. Also updates the associated cache.
-     *
-     * @param \stdClass|array $subscription Subscription record.
-     * @throws \coding_exception If something goes wrong
-     */
-    public static function update_subscription($subscription) {
-        global $DB;
-
-        if (is_array($subscription)) {
-            $subscription = (object)$subscription;
-        }
-        if (empty($subscription->id) || !$DB->record_exists('event_subscriptions', array('id' => $subscription->id))) {
-            throw new \coding_exception('Cannot update a subscription without a valid id');
-        }
-
-        $DB->update_record('event_subscriptions', $subscription);
-
-        // Update cache.
-        $cache = \cache::make('core', 'calendar_subscriptions');
-        $cache->set($subscription->id, $subscription);
-
-        // Trigger event, calendar subscription updated.
-        $eventparams = array('userid' => $subscription->userid,
-            'objectid' => $subscription->id,
-            'context' => self::get_calendar_context($subscription),
-            'other' => array('eventtype' => $subscription->eventtype, 'courseid' => $subscription->courseid)
-        );
-        $event = \core\event\calendar_subscription_updated::create($eventparams);
-        $event->trigger();
-    }
-
-    /**
-     * Checks to see if the user can edit a given subscription feed.
-     *
-     * @param mixed $subscriptionorid Subscription object or id
-     * @return bool true if current user can edit the subscription else false
-     */
-    public static function can_edit_subscription($subscriptionorid) {
-        if (is_array($subscriptionorid)) {
-            $subscription = (object)$subscriptionorid;
-        } else if (is_object($subscriptionorid)) {
-            $subscription = $subscriptionorid;
-        } else {
-            $subscription = self::get_subscription($subscriptionorid);
-        }
-
-        $allowed = new \stdClass;
-        $courseid = $subscription->courseid;
-        $groupid = $subscription->groupid;
-
-        self::get_allowed_types($allowed, $courseid);
-        switch ($subscription->eventtype) {
-            case 'user':
-                return $allowed->user;
-            case 'course':
-                if (isset($allowed->courses[$courseid])) {
-                    return $allowed->courses[$courseid];
-                } else {
-                    return false;
-                }
-            case 'site':
-                return $allowed->site;
-            case 'group':
-                if (isset($allowed->groups[$groupid])) {
-                    return $allowed->groups[$groupid];
-                } else {
-                    return false;
-                }
-            default:
-                return false;
-        }
-    }
-
-    /**
-     * Helper function to determine the context of a calendar subscription.
-     * Subscriptions can be created in two contexts COURSE, or USER.
-     *
-     * @param \stdClass $subscription
-     * @return \context instance
-     */
-    public static function get_calendar_context($subscription) {
-        // Determine context based on calendar type.
-        if ($subscription->eventtype === 'site') {
-            $context = \context_course::instance(SITEID);
-        } else if ($subscription->eventtype === 'group' || $subscription->eventtype === 'course') {
-            $context = \context_course::instance($subscription->courseid);
-        } else {
-            $context = \context_user::instance($subscription->userid);
-        }
-        return $context;
-    }
-
     /**
      * Get a list of action events for the logged in user by the given
      * timesort values.
index 1fb2e3d..5f55e28 100644 (file)
@@ -134,12 +134,12 @@ abstract class event_abstract_factory implements event_factory_interface {
         }
 
         $course = new std_proxy($dbrow->courseid, function($id) {
-            return \core_calendar\api::get_course_cached($this->coursecachereference, $id);
+            return calendar_get_course_cached($this->coursecachereference, $id);
         });
 
         if ($dbrow->groupid) {
             $group = new std_proxy($dbrow->groupid, function($id) {
-                return \core_calendar\api::get_group_cached($id);
+                return calendar_get_group_cached($id);
             });
         }
 
@@ -155,7 +155,7 @@ abstract class event_abstract_factory implements event_factory_interface {
                 $dbrow->modulename,
                 $dbrow->instance,
                 function($modulename, $instance) {
-                    return \core_calendar\api::get_module_cached(
+                    return calendar_get_module_cached(
                         $this->modulecachereference,
                         $modulename,
                         $instance
@@ -166,7 +166,7 @@ abstract class event_abstract_factory implements event_factory_interface {
 
         if ($dbrow->subscriptionid) {
             $subscription = new std_proxy($dbrow->subscriptionid, function($id) {
-                return \core_calendar\api::get_subscription($id);
+                return calendar_get_subscription($id);
             });
         }
 
index 13ea251..dc888f2 100644 (file)
@@ -159,10 +159,10 @@ class raw_event_retrieval_strategy implements raw_event_retrieval_strategy_inter
         $subqueryconditions = [];
 
         // Get the user's courses. Otherwise, get the default courses being shown by the calendar.
-        $usercourses = \core_calendar\api::get_default_courses();
+        $usercourses = calendar_get_default_courses();
 
         // Set calendar filters.
-        list($usercourses, $usergroups, $user) = \core_calendar\api::set_filters($usercourses, true);
+        list($usercourses, $usergroups, $user) = calendar_set_filters($usercourses, true);
         $subqueryparams = [];
 
         // Flag to indicate whether the query needs to exclude group overrides.
index 6ebb06e..93c6c4d 100644 (file)
@@ -59,7 +59,7 @@ if (!$course) {
 }
 
 // Check the user has the required capabilities to edit an event
-if (!\core_calendar\api::can_edit_event($event)) {
+if (!calendar_edit_event_allowed($event)) {
     print_error('nopermissions');
 }
 
index dcf6558..66c6a6f 100644 (file)
@@ -94,7 +94,7 @@ if ($courseid != SITEID && !empty($courseid)) {
     $issite = false;
 } else {
     $course = get_site();
-    $courses = \core_calendar\api::get_default_courses();
+    $courses = calendar_get_default_courses();
     $issite = true;
 }
 require_login($course, false);
@@ -114,7 +114,7 @@ $formoptions = new stdClass;
 if ($eventid !== 0) {
     $title = get_string('editevent', 'calendar');
     $event = calendar_event::load($eventid);
-    if (!\core_calendar\api::can_edit_event($event)) {
+    if (!calendar_edit_event_allowed($event)) {
         print_error('nopermissions');
     }
     $event->action = $action;
@@ -122,7 +122,7 @@ if ($eventid !== 0) {
     $event->timedurationuntil = $event->timestart + $event->timeduration;
     $event->count_repeats();
 
-    if (!\core_calendar\api::can_add_event($event)) {
+    if (!calendar_add_event_allowed($event)) {
         print_error('nopermissions');
     }
 
@@ -134,7 +134,7 @@ if ($eventid !== 0) {
 
 } else {
     $title = get_string('newevent', 'calendar');
-    \core_calendar\api::get_allowed_types($formoptions->eventtypes, $course);
+    calendar_get_allowed_types($formoptions->eventtypes, $course);
     $event = new stdClass();
     $event->action = $action;
     $event->course = $courseid;
@@ -150,7 +150,7 @@ if ($eventid !== 0) {
     }
     $event->timestart = $time;
     $event = new calendar_event($event);
-    if (!\core_calendar\api::can_add_event($event)) {
+    if (!calendar_add_event_allowed($event)) {
         print_error('nopermissions');
     }
 }
index 302513a..979c892 100644 (file)
@@ -82,7 +82,7 @@ if ($courseid != SITEID && !empty($courseid)) {
     $issite = false;
 } else {
     $course = get_site();
-    $courses = \core_calendar\api::get_default_courses();
+    $courses = calendar_get_default_courses();
     $issite = true;
 }
 require_course_login($course);
@@ -108,7 +108,7 @@ if ($issite) {
     $PAGE->navbar->add($course->shortname, new moodle_url('/course/view.php', array('id'=>$course->id)));
 }
 $link = new moodle_url(CALENDAR_URL.'view.php', array('view'=>'upcoming', 'course'=>$calendar->courseid));
-$PAGE->navbar->add(get_string('calendar', 'calendar'), \core_calendar\api::get_link_href($link, 0, 0, 0, $time));
+$PAGE->navbar->add(get_string('calendar', 'calendar'), calendar_get_link_href($link, 0, 0, 0, $time));
 $PAGE->navbar->add($pagetitle);
 
 $PAGE->set_title($course->shortname.': '.get_string('calendar', 'calendar').': '.$pagetitle);
@@ -133,7 +133,7 @@ $formdata = array(
     // If today it's weekend, give the "next week" option.
     'allownextweek' => $weekend & (1 << $now['wday']),
     // If it's the last week of the month, give the "next month" option.
-    'allownextmonth' => \core_calendar\api::get_days_in_month($now['mon'], $now['year']) - $now['mday'] < $numberofdaysinweek,
+    'allownextmonth' => calendar_days_in_month($now['mon'], $now['year']) - $now['mday'] < $numberofdaysinweek,
     // If today it's weekend but tomorrow it isn't, do NOT give the "this week" option.
     'allowthisweek' => !(($weekend & (1 << $now['wday'])) && !($weekend & (1 << (($now['wday'] + 1) % $numberofdaysinweek))))
 );
index 6b300ce..e3abec8 100644 (file)
@@ -60,7 +60,7 @@ if (!empty($generateurl)) {
 if(!empty($what) && !empty($time)) {
     if(in_array($what, $allowed_what) && in_array($time, $allowed_time)) {
         $courses = enrol_get_users_courses($user->id, true, 'id, visible, shortname');
-        // Array of courses that we will pass to \core_calendar\api::get_events() which
+        // Array of courses that we will pass to calendar_get_events() which
         // is initially set to the list of the user's courses.
         $paramcourses = $courses;
         if ($what == 'all' || $what == 'groups') {
@@ -95,12 +95,12 @@ if(!empty($what) && !empty($time)) {
 
         switch($time) {
             case 'weeknow':
-                $startweekday = \core_calendar\api::get_starting_weekday();
+                $startweekday = calendar_get_starting_weekday();
                 $startmonthday = find_day_in_month($now['mday'] - ($numberofdaysinweek - 1), $startweekday, $now['mon'], $now['year']);
                 $startmonth = $now['mon'];
                 $startyear = $now['year'];
-                if ($startmonthday > \core_calendar\api::get_days_in_month($startmonth, $startyear)) {
-                    list($startmonth, $startyear) = \core_calendar\api::get_next_month($startmonth, $startyear);
+                if ($startmonthday > calendar_days_in_month($startmonth, $startyear)) {
+                    list($startmonth, $startyear) = calendar_add_month($startmonth, $startyear);
                     $startmonthday = find_day_in_month(1, $startweekday, $startmonth, $startyear);
                 }
                 $gregoriandate = $calendartype->convert_to_gregorian($startyear, $startmonth, $startmonthday);
@@ -110,8 +110,8 @@ if(!empty($what) && !empty($time)) {
                 $endmonthday = $startmonthday + $numberofdaysinweek;
                 $endmonth = $startmonth;
                 $endyear = $startyear;
-                if ($endmonthday > \core_calendar\api::get_days_in_month($endmonth, $endyear)) {
-                    list($endmonth, $endyear) = \core_calendar\api::get_next_month($endmonth, $endyear);
+                if ($endmonthday > calendar_days_in_month($endmonth, $endyear)) {
+                    list($endmonth, $endyear) = calendar_add_month($endmonth, $endyear);
                     $endmonthday = find_day_in_month(1, $startweekday, $endmonth, $endyear);
                 }
                 $gregoriandate = $calendartype->convert_to_gregorian($endyear, $endmonth, $endmonthday);
@@ -119,12 +119,12 @@ if(!empty($what) && !empty($time)) {
                     $gregoriandate['hour'], $gregoriandate['minute']);
             break;
             case 'weeknext':
-                $startweekday = \core_calendar\api::get_starting_weekday();
+                $startweekday = calendar_get_starting_weekday();
                 $startmonthday = find_day_in_month($now['mday'] + 1, $startweekday, $now['mon'], $now['year']);
                 $startmonth = $now['mon'];
                 $startyear = $now['year'];
-                if ($startmonthday > \core_calendar\api::get_days_in_month($startmonth, $startyear)) {
-                    list($startmonth, $startyear) = \core_calendar\api::get_next_month($startmonth, $startyear);
+                if ($startmonthday > calendar_days_in_month($startmonth, $startyear)) {
+                    list($startmonth, $startyear) = calendar_add_month($startmonth, $startyear);
                     $startmonthday = find_day_in_month(1, $startweekday, $startmonth, $startyear);
                 }
                 $gregoriandate = $calendartype->convert_to_gregorian($startyear, $startmonth, $startmonthday);
@@ -134,8 +134,8 @@ if(!empty($what) && !empty($time)) {
                 $endmonthday = $startmonthday + $numberofdaysinweek;
                 $endmonth = $startmonth;
                 $endyear = $startyear;
-                if ($endmonthday > \core_calendar\api::get_days_in_month($endmonth, $endyear)) {
-                    list($endmonth, $endyear) = \core_calendar\api::get_next_month($endmonth, $endyear);
+                if ($endmonthday > calendar_days_in_month($endmonth, $endyear)) {
+                    list($endmonth, $endyear) = calendar_add_month($endmonth, $endyear);
                     $endmonthday = find_day_in_month(1, $startweekday, $endmonth, $endyear);
                 }
                 $gregoriandate = $calendartype->convert_to_gregorian($endyear, $endmonth, $endmonthday);
@@ -148,11 +148,11 @@ if(!empty($what) && !empty($time)) {
 
                 $timestart = make_timestamp($gregoriandate['year'], $gregoriandate['month'], $gregoriandate['day'],
                     $gregoriandate['hour'], $gregoriandate['minute']);
-                $timeend = $timestart + (\core_calendar\api::get_days_in_month($now['mon'], $now['year']) * DAYSECS);
+                $timeend = $timestart + (calendar_days_in_month($now['mon'], $now['year']) * DAYSECS);
             break;
             case 'monthnext':
                 // Get the next month for this calendar.
-                list($nextmonth, $nextyear) = \core_calendar\api::get_next_month($now['mon'], $now['year']);
+                list($nextmonth, $nextyear) = calendar_add_month($now['mon'], $now['year']);
 
                 // Convert to gregorian.
                 $gregoriandate = $calendartype->convert_to_gregorian($nextyear, $nextmonth, 1);
@@ -160,7 +160,7 @@ if(!empty($what) && !empty($time)) {
                 // Create the timestamps.
                 $timestart = make_timestamp($gregoriandate['year'], $gregoriandate['month'], $gregoriandate['day'],
                     $gregoriandate['hour'], $gregoriandate['minute']);
-                $timeend = $timestart + (\core_calendar\api::get_days_in_month($nextmonth, $nextyear) * DAYSECS);
+                $timeend = $timestart + (calendar_days_in_month($nextmonth, $nextyear) * DAYSECS);
             break;
             case 'recentupcoming':
                 //Events in the last 5 or next 60 days
@@ -180,7 +180,7 @@ if(!empty($what) && !empty($time)) {
         die();
     }
 }
-$events = \core_calendar\api::get_events($timestart, $timeend, $users, $groups, array_keys($paramcourses), false);
+$events = calendar_get_events($timestart, $timeend, $users, $groups, array_keys($paramcourses), false);
 
 $ical = new iCalendar;
 $ical->add_property('method', 'PUBLISH');
index 6365dd2..c6208f4 100644 (file)
@@ -86,7 +86,7 @@ class core_calendar_external extends external_api {
             $eventobj = calendar_event::load($event['eventid']);
 
             // Let's check if the user is allowed to delete an event.
-            if (!\core_calendar\api::can_edit_event($eventobj)) {
+            if (!calendar_edit_event_allowed($eventobj)) {
                 throw new moodle_exception("nopermissions");
             }
             // Time to do the magic.
@@ -233,14 +233,14 @@ class core_calendar_external extends external_api {
         }
 
         // Event list does not check visibility and permissions, we'll check that later.
-        $eventlist = \core_calendar\api::get_events($params['options']['timestart'], $params['options']['timeend'],
+        $eventlist = calendar_get_events($params['options']['timestart'], $params['options']['timeend'],
             $funcparam['users'], $funcparam['groups'], $funcparam['courses'], true, $params['options']['ignorehidden']);
 
         // WS expects arrays.
         $events = array();
 
         // We need to get events asked for eventids.
-        if ($eventsbyid = \core_calendar\api::get_events_by_id($params['events']['eventids'])) {
+        if ($eventsbyid = calendar_get_events_by_id($params['events']['eventids'])) {
             $eventlist += $eventsbyid;
         }
 
@@ -265,7 +265,7 @@ class core_calendar_external extends external_api {
                             (!empty($eventobj->groupid) && in_array($eventobj->groupid, $groups)) ||
                             (!empty($eventobj->courseid) && in_array($eventobj->courseid, $courses)) ||
                             ($USER->id == $eventobj->userid) ||
-                            (\core_calendar\api::can_edit_event($eventid))) {
+                            (calendar_edit_event_allowed($eventid))) {
                     $events[$eventid] = $event;
                 } else {
                     $warnings[] = array('item' => $eventid, 'warningcode' => 'nopermissions', 'message' => 'you do not have permissions to view this event');
@@ -623,7 +623,7 @@ class core_calendar_external extends external_api {
             $eventobj = new calendar_event($event);
 
             // Let's check if the user is allowed to delete an event.
-            if (!\core_calendar\api::can_add_event($eventobj)) {
+            if (!calendar_add_event_allowed($eventobj)) {
                 $warnings [] = array('item' => $event['name'], 'warningcode' => 'nopermissions', 'message' => 'you do not have permissions to create this event');
                 continue;
             }
index 9f885d5..8a7b200 100644 (file)
@@ -210,7 +210,7 @@ class calendar_event {
         }
 
         if (!empty($data->subscriptionid)) {
-            $data->subscription = \core_calendar\api::get_subscription($data->subscriptionid);
+            $data->subscription = calendar_get_subscription($data->subscriptionid);
         }
 
         // Default to a user event.
@@ -438,7 +438,7 @@ class calendar_event {
         if (empty($this->properties->id) || $this->properties->id < 1) {
 
             if ($checkcapability) {
-                if (!\core_calendar\api::can_add_event($this->properties)) {
+                if (!calendar_add_event_allowed($this->properties)) {
                     print_error('nopermissiontoupdatecalendar');
                 }
             }
@@ -549,7 +549,7 @@ class calendar_event {
         } else {
 
             if ($checkcapability) {
-                if (!\core_calendar\api::can_edit_event($this->properties)) {
+                if (!calendar_edit_event_allowed($this->properties)) {
                     print_error('nopermissiontoupdatecalendar');
                 }
             }
@@ -994,7 +994,7 @@ class calendar_information {
     public function prepare_for_view(stdClass $course, array $coursestoload, $ignorefilters = false) {
         $this->courseid = $course->id;
         $this->course = $course;
-        list($courses, $group, $user) = \core_calendar\api::set_filters($coursestoload, $ignorefilters);
+        list($courses, $group, $user) = calendar_set_filters($coursestoload, $ignorefilters);
         $this->courses = $courses;
         $this->groups = $group;
         $this->users = $user;
@@ -1163,10 +1163,10 @@ function calendar_get_events($tstart, $tend, $users, $groups, $courses, $withdur
     $subqueryconditions = [];
 
     // Get the user's courses. Otherwise, get the default courses being shown by the calendar.
-    $usercourses = \core_calendar\api::get_default_courses();
+    $usercourses = calendar_get_default_courses();
 
     // Set calendar filters.
-    list($usercourses, $usergroups, $user) = \core_calendar\api::set_filters($usercourses, true);
+    list($usercourses, $usergroups, $user) = calendar_set_filters($usercourses, true);
     $subqueryparams = [];
 
     // Flag to indicate whether the query needs to exclude group overrides.
@@ -1265,7 +1265,8 @@ function calendar_get_events($tstart, $tend, $users, $groups, $courses, $withdur
  * @return array array of days
  */
 function calendar_get_days() {
-    return \core_calendar\api::get_days();
+    $calendartype = \core_calendar\type_factory::get_calendar_instance();
+    return $calendartype->get_weekdays();
 }
 
 /**
@@ -1277,7 +1278,16 @@ function calendar_get_days() {
  * @throws moodle_exception for an invalid id
  */
 function calendar_get_subscription($id) {
-    return \core_calendar\api::get_subscription($id);
+    global $DB;
+
+    $cache = \cache::make('core', 'calendar_subscriptions');
+    $subscription = $cache->get($id);
+    if (empty($subscription)) {
+        $subscription = $DB->get_record('event_subscriptions', array('id' => $id), '*', MUST_EXIST);
+        $cache->set($id, $subscription);
+    }
+
+    return $subscription;
 }
 
 /**
@@ -1288,7 +1298,8 @@ function calendar_get_subscription($id) {
  * @return int
  */
 function calendar_get_starting_weekday() {
-    return \core_calendar\api::get_starting_weekday();
+    $calendartype = \core_calendar\type_factory::get_calendar_instance();
+    return $calendartype->get_starting_weekday();
 }
 
 /**
@@ -1307,8 +1318,335 @@ function calendar_get_starting_weekday() {
  */
 function calendar_get_mini($courses, $groups, $users, $calmonth = false, $calyear = false, $placement = false,
                            $courseid = false, $time = 0) {
-    return \core_calendar\api::get_mini_calendar($courses, $groups, $users, $calmonth, $calyear, $placement,
-        $courseid, $time);
+    global $CFG, $OUTPUT;
+
+    // Get the calendar type we are using.
+    $calendartype = \core_calendar\type_factory::get_calendar_instance();
+
+    $display = new \stdClass;
+
+    // Assume we are not displaying this month for now.
+    $display->thismonth = false;
+
+    $content = '';
+
+    // Do this check for backwards compatibility.
+    // The core should be passing a timestamp rather than month and year.
+    // If a month and year are passed they will be in Gregorian.
+    if (!empty($calmonth) && !empty($calyear)) {
+        // Ensure it is a valid date, else we will just set it to the current timestamp.
+        if (checkdate($calmonth, 1, $calyear)) {
+            $time = make_timestamp($calyear, $calmonth, 1);
+        } else {
+            $time = time();
+        }
+        $date = usergetdate($time);
+        if ($calmonth == $date['mon'] && $calyear == $date['year']) {
+            $display->thismonth = true;
+        }
+        // We can overwrite date now with the date used by the calendar type,
+        // if it is not Gregorian, otherwise there is no need as it is already in Gregorian.
+        if ($calendartype->get_name() != 'gregorian') {
+            $date = $calendartype->timestamp_to_date_array($time);
+        }
+    } else if (!empty($time)) {
+        // Get the specified date in the calendar type being used.
+        $date = $calendartype->timestamp_to_date_array($time);
+        $thisdate = $calendartype->timestamp_to_date_array(time());
+        if ($date['month'] == $thisdate['month'] && $date['year'] == $thisdate['year']) {
+            $display->thismonth = true;
+            // If we are the current month we want to set the date to the current date, not the start of the month.
+            $date = $thisdate;
+        }
+    } else {
+        // Get the current date in the calendar type being used.
+        $time = time();
+        $date = $calendartype->timestamp_to_date_array($time);
+        $display->thismonth = true;
+    }
+
+    list($d, $m, $y) = array($date['mday'], $date['mon'], $date['year']); // This is what we want to display.
+
+    // Get Gregorian date for the start of the month.
+    $gregoriandate = $calendartype->convert_to_gregorian($date['year'], $date['mon'], 1);
+
+    // Store the gregorian date values to be used later.
+    list($gy, $gm, $gd, $gh, $gmin) = array($gregoriandate['year'], $gregoriandate['month'], $gregoriandate['day'],
+        $gregoriandate['hour'], $gregoriandate['minute']);
+
+    // Get the max number of days in this month for this calendar type.
+    $display->maxdays = calendar_days_in_month($m, $y);
+    // Get the starting week day for this month.
+    $startwday = dayofweek(1, $m, $y);
+    // Get the days in a week.
+    $daynames = calendar_get_days();
+    // Store the number of days in a week.
+    $numberofdaysinweek = $calendartype->get_num_weekdays();
+
+    // Set the min and max weekday.
+    $display->minwday = calendar_get_starting_weekday();
+    $display->maxwday = $display->minwday + ($numberofdaysinweek - 1);
+
+    // These are used for DB queries, so we want unixtime, so we need to use Gregorian dates.
+    $display->tstart = make_timestamp($gy, $gm, $gd, $gh, $gmin, 0);
+    $display->tend = $display->tstart + ($display->maxdays * DAYSECS) - 1;
+
+    // Align the starting weekday to fall in our display range.
+    // This is simple, not foolproof.
+    if ($startwday < $display->minwday) {
+        $startwday += $numberofdaysinweek;
+    }
+
+    // Get the events matching our criteria. Don't forget to offset the timestamps for the user's TZ.
+    $events = calendar_get_events($display->tstart, $display->tend, $users, $groups, $courses);
+
+    // Set event course class for course events.
+    if (!empty($events)) {
+        foreach ($events as $eventid => $event) {
+            if (!empty($event->modulename)) {
+                $cm = get_coursemodule_from_instance($event->modulename, $event->instance);
+                if (!\core_availability\info_module::is_user_visible($cm, 0, false)) {
+                    unset($events[$eventid]);
+                }
+            }
+        }
+    }
+
+    // This is either a genius idea or an idiot idea: in order to not complicate things, we use this rule: if, after
+    // possibly removing SITEID from $courses, there is only one course left, then clicking on a day in the month
+    // will also set the $SESSION->cal_courses_shown variable to that one course. Otherwise, we 'd need to add extra
+    // arguments to this function.
+    $hrefparams = array();
+    if (!empty($courses)) {
+        $courses = array_diff($courses, array(SITEID));
+        if (count($courses) == 1) {
+            $hrefparams['course'] = reset($courses);
+        }
+    }
+
+    // We want to have easy access by day, since the display is on a per-day basis.
+    calendar_events_by_day($events, $m, $y, $eventsbyday, $durationbyday, $typesbyday, $courses);
+
+    // Accessibility: added summary and <abbr> elements.
+    $summary = get_string('calendarheading', 'calendar', userdate($display->tstart, get_string('strftimemonthyear')));
+    // Begin table.
+    $content .= '<table class="minicalendar calendartable" summary="' . $summary . '">';
+    if (($placement !== false) && ($courseid !== false)) {
+        $content .= '<caption>' . calendar_top_controls($placement,
+                array('id' => $courseid, 'time' => $time)) . '</caption>';
+    }
+    $content .= '<tr class="weekdays">'; // Header row: day names.
+
+    // Print out the names of the weekdays.
+    for ($i = $display->minwday; $i <= $display->maxwday; $i++) {
+        $pos = $i % $numberofdaysinweek;
+        $content .= '<th scope="col"><abbr title="' . $daynames[$pos]['fullname'] . '">' .
+            $daynames[$pos]['shortname'] . "</abbr></th>\n";
+    }
+
+    $content .= '</tr><tr>'; // End of day names; prepare for day numbers.
+
+    // For the table display. $week is the row; $dayweek is the column.
+    $dayweek = $startwday;
+
+    // Padding (the first week may have blank days in the beginning).
+    for ($i = $display->minwday; $i < $startwday; ++$i) {
+        $content .= '<td class="dayblank">&nbsp;</td>' ."\n";
+    }
+
+    $weekend = CALENDAR_DEFAULT_WEEKEND;
+    if (isset($CFG->calendar_weekend)) {
+        $weekend = intval($CFG->calendar_weekend);
+    }
+
+    // Now display all the calendar.
+    $daytime = strtotime('-1 day', $display->tstart);
+    for ($day = 1; $day <= $display->maxdays; ++$day, ++$dayweek) {
+        $cellattributes = array();
+        $daytime = strtotime('+1 day', $daytime);
+        if ($dayweek > $display->maxwday) {
+            // We need to change week (table row).
+            $content .= '</tr><tr>';
+            $dayweek = $display->minwday;
+        }
+
+        // Reset vars.
+        if ($weekend & (1 << ($dayweek % $numberofdaysinweek))) {
+            // Weekend. This is true no matter what the exact range is.
+            $class = 'weekend day';
+        } else {
+            // Normal working day.
+            $class = 'day';
+        }
+
+        $eventids = array();
+        if (!empty($eventsbyday[$day])) {
+            $eventids = $eventsbyday[$day];
+        }
+
+        if (!empty($durationbyday[$day])) {
+            $eventids = array_unique(array_merge($eventids, $durationbyday[$day]));
+        }
+
+        $finishclass = false;
+
+        if (!empty($eventids)) {
+            // There is at least one event on this day.
+            $class .= ' hasevent';
+            $hrefparams['view'] = 'day';
+            $dayhref = calendar_get_link_href(new \moodle_url(CALENDAR_URL . 'view.php', $hrefparams), 0, 0, 0, $daytime);
+
+            $popupcontent = '';
+            foreach ($eventids as $eventid) {
+                if (!isset($events[$eventid])) {
+                    continue;
+                }
+                $event = new \calendar_event($events[$eventid]);
+                $popupalt  = '';
+                $component = 'moodle';
+                if (!empty($event->modulename)) {
+                    $popupicon = 'icon';
+                    $popupalt  = $event->modulename;
+                    $component = $event->modulename;
+                } else if ($event->courseid == SITEID) { // Site event.
+                    $popupicon = 'i/siteevent';
+                } else if ($event->courseid != 0 && $event->courseid != SITEID
+                    && $event->groupid == 0) { // Course event.
+                    $popupicon = 'i/courseevent';
+                } else if ($event->groupid) { // Group event.
+                    $popupicon = 'i/groupevent';
+                } else { // Must be a user event.
+                    $popupicon = 'i/userevent';
+                }
+
+                if ($event->timeduration) {
+                    $startdate = $calendartype->timestamp_to_date_array($event->timestart);
+                    $enddate = $calendartype->timestamp_to_date_array($event->timestart + $event->timeduration - 1);
+                    if ($enddate['mon'] == $m && $enddate['year'] == $y && $enddate['mday'] == $day) {
+                        $finishclass = true;
+                    }
+                }
+
+                $dayhref->set_anchor('event_' . $event->id);
+
+                $popupcontent .= \html_writer::start_tag('div');
+                $popupcontent .= $OUTPUT->pix_icon($popupicon, $popupalt, $component);
+                // Show ical source if needed.
+                if (!empty($event->subscription) && $CFG->calendar_showicalsource) {
+                    $a = new \stdClass();
+                    $a->name = format_string($event->name, true);
+                    $a->source = $event->subscription->name;
+                    $name = get_string('namewithsource', 'calendar', $a);
+                } else {
+                    if ($finishclass) {
+                        $samedate = $startdate['mon'] == $enddate['mon'] &&
+                            $startdate['year'] == $enddate['year'] &&
+                            $startdate['mday'] == $enddate['mday'];
+
+                        if ($samedate) {
+                            $name = format_string($event->name, true);
+                        } else {
+                            $name = format_string($event->name, true) . ' (' . get_string('eventendtime', 'calendar') . ')';
+                        }
+                    } else {
+                        $name = format_string($event->name, true);
+                    }
+                }
+                $popupcontent .= \html_writer::link($dayhref, $name);
+                $popupcontent .= \html_writer::end_tag('div');
+            }
+
+            if ($display->thismonth && $day == $d) {
+                $popupdata = calendar_get_popup(true, $daytime, $popupcontent);
+            } else {
+                $popupdata = calendar_get_popup(false, $daytime, $popupcontent);
+            }
+
+            // Class and cell content.
+            if (isset($typesbyday[$day]['startglobal'])) {
+                $class .= ' calendar_event_global';
+            } else if (isset($typesbyday[$day]['startcourse'])) {
+                $class .= ' calendar_event_course';
+            } else if (isset($typesbyday[$day]['startgroup'])) {
+                $class .= ' calendar_event_group';
+            } else if (isset($typesbyday[$day]['startuser'])) {
+                $class .= ' calendar_event_user';
+            }
+            if ($finishclass) {
+                $class .= ' duration_finish';
+            }
+            $data = array(
+                'url' => $dayhref,
+                'day' => $day,
+                'content' => $popupdata['data-core_calendar-popupcontent'],
+                'title' => $popupdata['data-core_calendar-title']
+            );
+            $cell = $OUTPUT->render_from_template('core_calendar/minicalendar_day_link', $data);
+        } else {
+            $cell = $day;
+        }
+
+        $durationclass = false;
+        if (isset($typesbyday[$day]['durationglobal'])) {
+            $durationclass = ' duration_global';
+        } else if (isset($typesbyday[$day]['durationcourse'])) {
+            $durationclass = ' duration_course';
+        } else if (isset($typesbyday[$day]['durationgroup'])) {
+            $durationclass = ' duration_group';
+        } else if (isset($typesbyday[$day]['durationuser'])) {
+            $durationclass = ' duration_user';
+        }
+        if ($durationclass) {
+            $class .= ' duration ' . $durationclass;
+        }
+
+        // If event has a class set then add it to the table day <td> tag.
+        // Note: only one colour for minicalendar.
+        if (isset($eventsbyday[$day])) {
+            foreach ($eventsbyday[$day] as $eventid) {
+                if (!isset($events[$eventid])) {
+                    continue;
+                }
+                $event = $events[$eventid];
+                if (!empty($event->class)) {
+                    $class .= ' ' . $event->class;
+                }
+                break;
+            }
+        }
+
+        if ($display->thismonth && $day == $d) {
+            // The current cell is for today - add appropriate classes and additional information for styling.
+            $class .= ' today';
+            $today = get_string('today', 'calendar') . ' ' . userdate(time(), get_string('strftimedayshort'));
+
+            if (!isset($eventsbyday[$day]) && !isset($durationbyday[$day])) {
+                $class .= ' eventnone';
+                $popupdata = calendar_get_popup(true, false);
+                $data = array(
+                    'url' => '#',
+                    'day' => $day,
+                    'content' => $popupdata['data-core_calendar-popupcontent'],
+                    'title' => $popupdata['data-core_calendar-title']
+                );
+                $cell = $OUTPUT->render_from_template('core_calendar/minicalendar_day_link', $data);
+            }
+            $cell = get_accesshide($today . ' ') . $cell;
+        }
+
+        // Just display it.
+        $cellattributes['class'] = $class;
+        $content .= \html_writer::tag('td', $cell, $cellattributes);
+    }
+
+    // Padding (the last week may have blank days at the end).
+    for ($i = $dayweek; $i <= $display->maxwday; ++$i) {
+        $content .= '<td class="dayblank">&nbsp;</td>';
+    }
+    $content .= '</tr>'; // Last row ends.
+
+    $content .= '</table>'; // Tabular display of days ends.
+    return $content;
 }
 
 /**
@@ -1323,7 +1661,23 @@ function calendar_get_mini($courses, $groups, $users, $calmonth = false, $calyea
  * @return string eventid for the calendar_tooltip popup window/layout.
  */
 function calendar_get_popup($today = false, $timestart, $popupcontent = '') {
-    return \core_calendar\api::get_popup($today, $timestart, $popupcontent);
+    $popupcaption = '';
+    if ($today) {
+        $popupcaption = get_string('today', 'calendar') . ' ';
+    }
+
+    if (false === $timestart) {
+        $popupcaption .= userdate(time(), get_string('strftimedayshort'));
+        $popupcontent = get_string('eventnone', 'calendar');
+
+    } else {
+        $popupcaption .= get_string('eventsfor', 'calendar', userdate($timestart, get_string('strftimedayshort')));
+    }
+
+    return array(
+        'data-core_calendar-title' => $popupcaption,
+        'data-core_calendar-popupcontent' => $popupcontent,
+    );
 }
 
 /**
@@ -1338,7 +1692,75 @@ function calendar_get_popup($today = false, $timestart, $popupcontent = '') {
  * @return array $output array of upcoming events
  */
 function calendar_get_upcoming($courses, $groups, $users, $daysinfuture, $maxevents, $fromtime=0) {
-    return \core_calendar\api::get_upcoming($courses, $groups, $users, $daysinfuture, $maxevents, $fromtime);
+    global $COURSE;
+
+    $display = new \stdClass;
+    $display->range = $daysinfuture; // How many days in the future we 'll look.
+    $display->maxevents = $maxevents;
+
+    $output = array();
+
+    $processed = 0;
+    $now = time(); // We 'll need this later.
+    $usermidnighttoday = usergetmidnight($now);
+
+    if ($fromtime) {
+        $display->tstart = $fromtime;
+    } else {
+        $display->tstart = $usermidnighttoday;
+    }
+
+    // This works correctly with respect to the user's DST, but it is accurate
+    // only because $fromtime is always the exact midnight of some day!
+    $display->tend = usergetmidnight($display->tstart + DAYSECS * $display->range + 3 * HOURSECS) - 1;
+
+    // Get the events matching our criteria.
+    $events = calendar_get_events($display->tstart, $display->tend, $users, $groups, $courses);
+
+    // This is either a genius idea or an idiot idea: in order to not complicate things, we use this rule: if, after
+    // possibly removing SITEID from $courses, there is only one course left, then clicking on a day in the month
+    // will also set the $SESSION->cal_courses_shown variable to that one course. Otherwise, we 'd need to add extra
+    // arguments to this function.
+    $hrefparams = array();
+    if (!empty($courses)) {
+        $courses = array_diff($courses, array(SITEID));
+        if (count($courses) == 1) {
+            $hrefparams['course'] = reset($courses);
+        }
+    }
+
+    if ($events !== false) {
+        $modinfo = get_fast_modinfo($COURSE);
+        foreach ($events as $event) {
+            if (!empty($event->modulename)) {
+                if ($event->courseid == $COURSE->id) {
+                    if (isset($modinfo->instances[$event->modulename][$event->instance])) {
+                        $cm = $modinfo->instances[$event->modulename][$event->instance];
+                        if (!$cm->uservisible) {
+                            continue;
+                        }
+                    }
+                } else {
+                    if (!$cm = get_coursemodule_from_instance($event->modulename, $event->instance)) {
+                        continue;
+                    }
+                    if (!\core_availability\info_module::is_user_visible($cm, 0, false)) {
+                        continue;
+                    }
+                }
+            }
+
+            if ($processed >= $display->maxevents) {
+                break;
+            }
+
+            $event->time = calendar_format_event_time($event, $now, $hrefparams);
+            $output[] = $event;
+            $processed++;
+        }
+    }
+
+    return $output;
 }
 
 /**
@@ -1348,29 +1770,33 @@ function calendar_get_upcoming($courses, $groups, $users, $daysinfuture, $maxeve
  * @return string a link to the course (as HTML); empty if the course id is invalid
  */
 function calendar_get_courselink($courseid) {
-    return \core_calendar\api::get_courselink($courseid);
+    if (!$courseid) {
+        return '';
+    }
+
+    calendar_get_course_cached($coursecache, $courseid);
+    $context = \context_course::instance($courseid);
+    $fullname = format_string($coursecache[$courseid]->fullname, true, array('context' => $context));
+    $url = new \moodle_url('/course/view.php', array('id' => $courseid));
+    $link = \html_writer::link($url, $fullname);
+
+    return $link;
 }
 
 /**
  * Get current module cache.
  *
- * @param array $coursecache list of course cache
+ * @param array $modulecache in memory module cache
  * @param string $modulename name of the module
  * @param int $instance module instance number
  * @return stdClass|bool $module information
  */
-function calendar_get_module_cached(&$coursecache, $modulename, $instance) {
-    // We have a new implementation of this function in the calendar API class,
-    // so the old implementation must remain here.
-    $module = get_coursemodule_from_instance($modulename, $instance);
-
-    if ($module === false) {
-        return false;
+function calendar_get_module_cached(&$modulecache, $modulename, $instance) {
+    if (!isset($modulecache[$modulename . '_' . $instance])) {
+        $modulecache[$modulename . '_' . $instance] = get_coursemodule_from_instance($modulename, $instance);
     }
-    if (!calendar_get_course_cached($coursecache, $module->course)) {
-        return false;
-    }
-    return $module;
+
+    return $modulecache[$modulename . '_' . $instance];
 }
 
 /**
@@ -1381,7 +1807,10 @@ function calendar_get_module_cached(&$coursecache, $modulename, $instance) {
  * @return stdClass $coursecache[$courseid] return the specific course cache
  */
 function calendar_get_course_cached(&$coursecache, $courseid) {
-    return \core_calendar\api::get_course_cached($coursecache, $courseid);
+    if (!isset($coursecache[$courseid])) {
+        $coursecache[$courseid] = get_course($courseid);
+    }
+    return $coursecache[$courseid];
 }
 
 /**
@@ -1391,7 +1820,11 @@ function calendar_get_course_cached(&$coursecache, $courseid) {
  * @return stdClass group object with fields 'id', 'name' and 'courseid'
  */
 function calendar_get_group_cached($groupid) {
-    return \core_calendar\api::get_group_cached($groupid);
+    static $groupscache = array();
+    if (!isset($groupscache[$groupid])) {
+        $groupscache[$groupid] = groups_get_group($groupid, 'id,name,courseid');
+    }
+    return $groupscache[$groupid];
 }
 
 /**
@@ -1401,7 +1834,61 @@ function calendar_get_group_cached($groupid) {
  * @return stdClass $event metadata
  */
 function calendar_add_event_metadata($event) {
-    return \core_calendar\api::add_event_metadata($event);
+    global $CFG, $OUTPUT;
+
+    // Support multilang in event->name.
+    $event->name = format_string($event->name, true);
+
+    if (!empty($event->modulename)) { // Activity event.
+        // The module name is set. I will assume that it has to be displayed, and
+        // also that it is an automatically-generated event. And of course that the
+        // fields for get_coursemodule_from_instance are set correctly.
+        $module = calendar_get_module_cached($coursecache, $event->modulename, $event->instance);
+
+        if ($module === false) {
+            return;
+        }
+
+        $modulename = get_string('modulename', $event->modulename);
+        if (get_string_manager()->string_exists($event->eventtype, $event->modulename)) {
+            // Will be used as alt text if the event icon.
+            $eventtype = get_string($event->eventtype, $event->modulename);
+        } else {
+            $eventtype = '';
+        }
+        $icon = $OUTPUT->image_url('icon', $event->modulename) . '';
+
+        $event->icon = '<img src="' . $icon . '" alt="' . $eventtype . '" title="' . $modulename . '" class="icon" />';
+        $event->referer = '<a href="' . $CFG->wwwroot . '/mod/' . $event->modulename . '/view.php?id=' .
+            $module->id . '">' . $event->name . '</a>';
+        $event->courselink = calendar_get_courselink($module->course);
+        $event->cmid = $module->id;
+    } else if ($event->courseid == SITEID) { // Site event.
+        $event->icon = '<img src="' . $OUTPUT->image_url('i/siteevent') . '" alt="' .
+            get_string('globalevent', 'calendar') . '" class="icon" />';
+        $event->cssclass = 'calendar_event_global';
+    } else if ($event->courseid != 0 && $event->courseid != SITEID && $event->groupid == 0) { // Course event.
+        $event->icon = '<img src="' . $OUTPUT->image_url('i/courseevent') . '" alt="' .
+            get_string('courseevent', 'calendar') . '" class="icon" />';
+        $event->courselink = calendar_get_courselink($event->courseid);
+        $event->cssclass = 'calendar_event_course';
+    } else if ($event->groupid) { // Group event.
+        if ($group = calendar_get_group_cached($event->groupid)) {
+            $groupname = format_string($group->name, true, \context_course::instance($group->courseid));
+        } else {
+            $groupname = '';
+        }
+        $event->icon = \html_writer::empty_tag('image', array('src' => $OUTPUT->image_url('i/groupevent'),
+            'alt' => get_string('groupevent', 'calendar'), 'title' => $groupname, 'class' => 'icon'));
+        $event->courselink = calendar_get_courselink($event->courseid) . ', ' . $groupname;
+        $event->cssclass = 'calendar_event_group';
+    } else if ($event->userid) { // User event.
+        $event->icon = '<img src="' . $OUTPUT->image_url('i/userevent') . '" alt="' .
+            get_string('userevent', 'calendar') . '" class="icon" />';
+        $event->cssclass = 'calendar_event_user';
+    }
+
+    return $event;
 }
 
 /**
@@ -1412,7 +1899,16 @@ function calendar_add_event_metadata($event) {
  * @return array Array of event entries, empty array if nothing found
  */
 function calendar_get_events_by_id($eventids) {
-    return \core_calendar\api::get_events_by_id($eventids);
+    global $DB;
+
+    if (!is_array($eventids) || empty($eventids)) {
+        return array();
+    }
+
+    list($wheresql, $params) = $DB->get_in_or_equal($eventids);
+    $wheresql = "id $wheresql";
+
+    return $DB->get_records_select('event', $wheresql, $params);
 }
 
 /**
@@ -1423,7 +1919,160 @@ function calendar_get_events_by_id($eventids) {
  * @return string $content return available control for the calender in html
  */
 function calendar_top_controls($type, $data) {
-    return \core_calendar\api::get_top_controls($type, $data);
+    global $PAGE, $OUTPUT;
+
+    // Get the calendar type we are using.
+    $calendartype = \core_calendar\type_factory::get_calendar_instance();
+
+    $content = '';
+
+    // Ensure course id passed if relevant.
+    $courseid = '';
+    if (!empty($data['id'])) {
+        $courseid = '&amp;course=' . $data['id'];
+    }
+
+    // If we are passing a month and year then we need to convert this to a timestamp to
+    // support multiple calendars. No where in core should these be passed, this logic
+    // here is for third party plugins that may use this function.
+    if (!empty($data['m']) && !empty($date['y'])) {
+        if (!isset($data['d'])) {
+            $data['d'] = 1;
+        }
+        if (!checkdate($data['m'], $data['d'], $data['y'])) {
+            $time = time();
+        } else {
+            $time = make_timestamp($data['y'], $data['m'], $data['d']);
+        }
+    } else if (!empty($data['time'])) {
+        $time = $data['time'];
+    } else {
+        $time = time();
+    }
+
+    // Get the date for the calendar type.
+    $date = $calendartype->timestamp_to_date_array($time);
+
+    $urlbase = $PAGE->url;
+
+    // We need to get the previous and next months in certain cases.
+    if ($type == 'frontpage' || $type == 'course' || $type == 'month') {
+        $prevmonth = calendar_sub_month($date['mon'], $date['year']);
+        $prevmonthtime = $calendartype->convert_to_gregorian($prevmonth[1], $prevmonth[0], 1);
+        $prevmonthtime = make_timestamp($prevmonthtime['year'], $prevmonthtime['month'], $prevmonthtime['day'],
+            $prevmonthtime['hour'], $prevmonthtime['minute']);
+
+        $nextmonth = calendar_add_month($date['mon'], $date['year']);
+        $nextmonthtime = $calendartype->convert_to_gregorian($nextmonth[1], $nextmonth[0], 1);
+        $nextmonthtime = make_timestamp($nextmonthtime['year'], $nextmonthtime['month'], $nextmonthtime['day'],
+            $nextmonthtime['hour'], $nextmonthtime['minute']);
+    }
+
+    switch ($type) {
+        case 'frontpage':
+            $prevlink = calendar_get_link_previous(get_string('monthprev', 'access'), $urlbase, false, false, false,
+                true, $prevmonthtime);
+            $nextlink = calendar_get_link_next(get_string('monthnext', 'access'), $urlbase, false, false, false, true,
+                $nextmonthtime);
+            $calendarlink = calendar_get_link_href(new \moodle_url(CALENDAR_URL . 'view.php', array('view' => 'month')),
+                false, false, false, $time);
+
+            if (!empty($data['id'])) {
+                $calendarlink->param('course', $data['id']);
+            }
+
+            $right = $nextlink;
+
+            $content .= \html_writer::start_tag('div', array('class' => 'calendar-controls'));
+            $content .= $prevlink . '<span class="hide"> | </span>';
+            $content .= \html_writer::tag('span', \html_writer::link($calendarlink,
+                userdate($time, get_string('strftimemonthyear')), array('title' => get_string('monththis', 'calendar'))
+            ), array('class' => 'current'));
+            $content .= '<span class="hide"> | </span>' . $right;
+            $content .= "<span class=\"clearer\"><!-- --></span>\n";
+            $content .= \html_writer::end_tag('div');
+
+            break;
+        case 'course':
+            $prevlink = calendar_get_link_previous(get_string('monthprev', 'access'), $urlbase, false, false, false,
+                true, $prevmonthtime);
+            $nextlink = calendar_get_link_next(get_string('monthnext', 'access'), $urlbase, false, false, false,
+                true, $nextmonthtime);
+            $calendarlink = calendar_get_link_href(new \moodle_url(CALENDAR_URL . 'view.php', array('view' => 'month')),
+                false, false, false, $time);
+
+            if (!empty($data['id'])) {
+                $calendarlink->param('course', $data['id']);
+            }
+
+            $content .= \html_writer::start_tag('div', array('class' => 'calendar-controls'));
+            $content .= $prevlink . '<span class="hide"> | </span>';
+            $content .= \html_writer::tag('span', \html_writer::link($calendarlink,
+                userdate($time, get_string('strftimemonthyear')), array('title' => get_string('monththis', 'calendar'))
+            ), array('class' => 'current'));
+            $content .= '<span class="hide"> | </span>' . $nextlink;
+            $content .= "<span class=\"clearer\"><!-- --></span>";
+            $content .= \html_writer::end_tag('div');
+            break;
+        case 'upcoming':
+            $calendarlink = calendar_get_link_href(new \moodle_url(CALENDAR_URL . 'view.php', array('view' => 'upcoming')),
+                false, false, false, $time);
+            if (!empty($data['id'])) {
+                $calendarlink->param('course', $data['id']);
+            }
+            $calendarlink = \html_writer::link($calendarlink, userdate($time, get_string('strftimemonthyear')));
+            $content .= \html_writer::tag('div', $calendarlink, array('class' => 'centered'));
+            break;
+        case 'display':
+            $calendarlink = calendar_get_link_href(new \moodle_url(CALENDAR_URL . 'view.php', array('view' => 'month')),
+                false, false, false, $time);
+            if (!empty($data['id'])) {
+                $calendarlink->param('course', $data['id']);
+            }
+            $calendarlink = \html_writer::link($calendarlink, userdate($time, get_string('strftimemonthyear')));
+            $content .= \html_writer::tag('h3', $calendarlink);
+            break;
+        case 'month':
+            $prevlink = calendar_get_link_previous(userdate($prevmonthtime, get_string('strftimemonthyear')),
+                'view.php?view=month' . $courseid . '&amp;', false, false, false, false, $prevmonthtime);
+            $nextlink = calendar_get_link_next(userdate($nextmonthtime, get_string('strftimemonthyear')),
+                'view.php?view=month' . $courseid . '&amp;', false, false, false, false, $nextmonthtime);
+
+            $content .= \html_writer::start_tag('div', array('class' => 'calendar-controls'));
+            $content .= $prevlink . '<span class="hide"> | </span>';
+            $content .= $OUTPUT->heading(userdate($time, get_string('strftimemonthyear')), 2, 'current');
+            $content .= '<span class="hide"> | </span>' . $nextlink;
+            $content .= '<span class="clearer"><!-- --></span>';
+            $content .= \html_writer::end_tag('div')."\n";
+            break;
+        case 'day':
+            $days = calendar_get_days();
+
+            $prevtimestamp = strtotime('-1 day', $time);
+            $nexttimestamp = strtotime('+1 day', $time);
+
+            $prevdate = $calendartype->timestamp_to_date_array($prevtimestamp);
+            $nextdate = $calendartype->timestamp_to_date_array($nexttimestamp);
+
+            $prevname = $days[$prevdate['wday']]['fullname'];
+            $nextname = $days[$nextdate['wday']]['fullname'];
+            $prevlink = calendar_get_link_previous($prevname, 'view.php?view=day' . $courseid . '&amp;', false, false,
+                false, false, $prevtimestamp);
+            $nextlink = calendar_get_link_next($nextname, 'view.php?view=day' . $courseid . '&amp;', false, false, false,
+                false, $nexttimestamp);
+
+            $content .= \html_writer::start_tag('div', array('class' => 'calendar-controls'));
+            $content .= $prevlink;
+            $content .= '<span class="hide"> | </span><span class="current">' .userdate($time,
+                    get_string('strftimedaydate')) . '</span>';
+            $content .= '<span class="hide"> | </span>' . $nextlink;
+            $content .= "<span class=\"clearer\"><!-- --></span>";
+            $content .= \html_writer::end_tag('div') . "\n";
+
+            break;
+    }
+
+    return $content;
 }
 
 /**
@@ -1434,7 +2083,42 @@ function calendar_top_controls($type, $data) {
  * @return string html content of the element
  */
 function calendar_filter_controls_element(moodle_url $url, $type) {
-    return \core_calendar\api::get_filter_controls_element($url, $type);
+    global $OUTPUT;
+
+    switch ($type) {
+        case CALENDAR_EVENT_GLOBAL:
+            $typeforhumans = 'global';
+            $class = 'calendar_event_global';
+            break;
+        case CALENDAR_EVENT_COURSE:
+            $typeforhumans = 'course';
+            $class = 'calendar_event_course';
+            break;
+        case CALENDAR_EVENT_GROUP:
+            $typeforhumans = 'groups';
+            $class = 'calendar_event_group';
+            break;
+        case CALENDAR_EVENT_USER:
+            $typeforhumans = 'user';
+            $class = 'calendar_event_user';
+            break;
+    }
+
+    if (calendar_show_event_type($type)) {
+        $icon = $OUTPUT->pix_icon('t/hide', get_string('hide'));
+        $str = get_string('hide' . $typeforhumans . 'events', 'calendar');
+    } else {
+        $icon = $OUTPUT->pix_icon('t/show', get_string('show'));
+        $str = get_string('show' . $typeforhumans . 'events', 'calendar');
+    }
+    $content = \html_writer::start_tag('li', array('class' => 'calendar_event'));
+    $content .= \html_writer::start_tag('a', array('href' => $url, 'rel' => 'nofollow'));
+    $content .= \html_writer::tag('span', $icon, array('class' => $class));
+    $content .= \html_writer::tag('span', $str, array('class' => 'eventname'));
+    $content .= \html_writer::end_tag('a');
+    $content .= \html_writer::end_tag('li');
+
+    return $content;
 }
 
 /**
@@ -1447,7 +2131,30 @@ function calendar_filter_controls_element(moodle_url $url, $type) {
  * @return string $content return filter controls in html
  */
 function calendar_filter_controls(moodle_url $returnurl) {
-    return \core_calendar\api::get_filter_controls($returnurl);
+    $groupevents = true;
+
+    $seturl = new \moodle_url('/calendar/set.php', array('return' => base64_encode($returnurl->out_as_local_url(false)),
+        'sesskey' => sesskey()));
+    $content = \html_writer::start_tag('ul');
+
+    $seturl->param('var', 'showglobal');
+    $content .= calendar_filter_controls_element($seturl, CALENDAR_EVENT_GLOBAL);
+
+    $seturl->param('var', 'showcourses');
+    $content .= calendar_filter_controls_element($seturl, CALENDAR_EVENT_COURSE);
+
+    if (isloggedin() && !isguestuser()) {
+        if ($groupevents) {
+            // This course MIGHT have group events defined, so show the filter.
+            $seturl->param('var', 'showgroups');
+            $content .= calendar_filter_controls_element($seturl, CALENDAR_EVENT_GROUP);
+        }
+        $seturl->param('var', 'showuser');
+        $content .= calendar_filter_controls_element($seturl, CALENDAR_EVENT_USER);
+    }
+    $content .= \html_writer::end_tag('ul');
+
+    return $content;
 }
 
 /**
@@ -1459,7 +2166,38 @@ function calendar_filter_controls(moodle_url $returnurl) {
  * @return string the formatted date/time
  */
 function calendar_day_representation($tstamp, $now = false, $usecommonwords = true) {
-    return \core_calendar\api::get_day_representation($tstamp, $now, $usecommonwords);
+    static $shortformat;
+
+    if (empty($shortformat)) {
+        $shortformat = get_string('strftimedayshort');
+    }
+
+    if ($now === false) {
+        $now = time();
+    }
+
+    // To have it in one place, if a change is needed.
+    $formal = userdate($tstamp, $shortformat);
+
+    $datestamp = usergetdate($tstamp);
+    $datenow = usergetdate($now);
+
+    if ($usecommonwords == false) {
+        // We don't want words, just a date.
+        return $formal;
+    } else if ($datestamp['year'] == $datenow['year'] && $datestamp['yday'] == $datenow['yday']) {
+        return get_string('today', 'calendar');
+    } else if (($datestamp['year'] == $datenow['year'] && $datestamp['yday'] == $datenow['yday'] - 1 ) ||
+        ($datestamp['year'] == $datenow['year'] - 1 && $datestamp['mday'] == 31 && $datestamp['mon'] == 12
+            && $datenow['yday'] == 1)) {
+        return get_string('yesterday', 'calendar');
+    } else if (($datestamp['year'] == $datenow['year'] && $datestamp['yday'] == $datenow['yday'] + 1 ) ||
+        ($datestamp['year'] == $datenow['year'] + 1 && $datenow['mday'] == 31 && $datenow['mon'] == 12
+            && $datestamp['yday'] == 1)) {
+        return get_string('tomorrow', 'calendar');
+    } else {
+        return $formal;
+    }
 }
 
 /**
@@ -1470,7 +2208,18 @@ function calendar_day_representation($tstamp, $now = false, $usecommonwords = tr
  * @return string the formatted date/time
  */
 function calendar_time_representation($time) {
-    return \core_calendar\api::get_time_representation($time);
+    static $langtimeformat = null;
+
+    if ($langtimeformat === null) {
+        $langtimeformat = get_string('strftimetime');
+    }
+
+    $timeformat = get_user_preferences('calendar_timeformat');
+    if (empty($timeformat)) {
+        $timeformat = get_config(null, 'calendar_site_timeformat');
+    }
+
+    return userdate($time, empty($timeformat) ? $langtimeformat : $timeformat);
 }
 
 /**
@@ -1485,7 +2234,30 @@ function calendar_time_representation($time) {
  * @return moodle_url|null $linkbase
  */
 function calendar_get_link_href($linkbase, $d, $m, $y, $time = 0) {
-    return \core_calendar\api::get_link_href($linkbase, $d, $m, $y, $time);
+    if (empty($linkbase)) {
+        return null;
+    }
+
+    if (!($linkbase instanceof \moodle_url)) {
+        $linkbase = new \moodle_url($linkbase);
+    }
+
+    // If a day, month and year were passed then convert it to a timestamp. If these were passed
+    // then we can assume the day, month and year are passed as Gregorian, as no where in core
+    // should we be passing these values rather than the time.
+    if (!empty($d) && !empty($m) && !empty($y)) {
+        if (checkdate($m, $d, $y)) {
+            $time = make_timestamp($y, $m, $d);
+        } else {
+            $time = time();
+        }
+    } else if (empty($time)) {
+        $time = time();
+    }
+
+    $linkbase->param('time', $time);
+
+    return $linkbase;
 }
 
 /**
@@ -1502,7 +2274,13 @@ function calendar_get_link_href($linkbase, $d, $m, $y, $time = 0) {
  * @return string HTML string.
  */
 function calendar_get_link_previous($text, $linkbase, $d, $m, $y, $accesshide = false, $time = 0) {
-    return \core_calendar\api::get_link_previous($text, $linkbase, $d, $m, $y, $accesshide, $time);
+    $href = calendar_get_link_href(new \moodle_url($linkbase), $d, $m, $y, $time);
+
+    if (empty($href)) {
+        return $text;
+    }
+
+    return link_arrow_left($text, (string)$href, $accesshide, 'previous');
 }
 
 /**
@@ -1519,7 +2297,13 @@ function calendar_get_link_previous($text, $linkbase, $d, $m, $y, $accesshide =
  * @return string HTML string.
  */
 function calendar_get_link_next($text, $linkbase, $d, $m, $y, $accesshide = false, $time = 0) {
-    return \core_calendar\api::get_link_next($text, $linkbase, $d, $m, $y, $accesshide, $time);
+    $href = calendar_get_link_href(new \moodle_url($linkbase), $d, $m, $y, $time);
+
+    if (empty($href)) {
+        return $text;
+    }
+
+    return link_arrow_right($text, (string)$href, $accesshide, 'next');
 }
 
 /**
@@ -1530,7 +2314,8 @@ function calendar_get_link_next($text, $linkbase, $d, $m, $y, $accesshide = fals
  * @return int
  */
 function calendar_days_in_month($month, $year) {
-    return \core_calendar\api::get_days_in_month($month, $year);
+    $calendartype = \core_calendar\type_factory::get_calendar_instance();
+    return $calendartype->get_num_days_in_month($year, $month);
 }
 
 /**
@@ -1541,7 +2326,8 @@ function calendar_days_in_month($month, $year) {
  * @return array the following month
  */
 function calendar_add_month($month, $year) {
-    return \core_calendar\api::get_next_month($month, $year);
+    $calendartype = \core_calendar\type_factory::get_calendar_instance();
+    return $calendartype->get_next_month($year, $month);
 }
 
 /**
@@ -1552,7 +2338,8 @@ function calendar_add_month($month, $year) {
  * @return array previous month
  */
 function calendar_sub_month($month, $year) {
-    return \core_calendar\api::get_prev_month($month, $year);
+    $calendartype = \core_calendar\type_factory::get_calendar_instance();
+    return $calendartype->get_prev_month($year, $month);
 }
 
 /**
@@ -1568,7 +2355,91 @@ function calendar_sub_month($month, $year) {
  * @return void
  */
 function calendar_events_by_day($events, $month, $year, &$eventsbyday, &$durationbyday, &$typesbyday, &$courses) {
-    \core_calendar\api::get_events_by_day($events, $month, $year, $eventsbyday, $durationbyday, $typesbyday, $courses);
+    $calendartype = \core_calendar\type_factory::get_calendar_instance();
+
+    $eventsbyday = array();
+    $typesbyday = array();
+    $durationbyday = array();
+
+    if ($events === false) {
+        return;
+    }
+
+    foreach ($events as $event) {
+        $startdate = $calendartype->timestamp_to_date_array($event->timestart);
+        if ($event->timeduration) {
+            $enddate = $calendartype->timestamp_to_date_array($event->timestart + $event->timeduration - 1);
+        } else {
+            $enddate = $startdate;
+        }
+
+        // Simple arithmetic: $year * 13 + $month is a distinct integer for each distinct ($year, $month) pair.
+        if (!($startdate['year'] * 13 + $startdate['mon'] <= $year * 13 + $month) &&
+            ($enddate['year'] * 13 + $enddate['mon'] >= $year * 13 + $month)) {
+            continue;
+        }
+
+        $eventdaystart = intval($startdate['mday']);
+
+        if ($startdate['mon'] == $month && $startdate['year'] == $year) {
+            // Give the event to its day.
+            $eventsbyday[$eventdaystart][] = $event->id;
+
+            // Mark the day as having such an event.
+            if ($event->courseid == SITEID && $event->groupid == 0) {
+                $typesbyday[$eventdaystart]['startglobal'] = true;
+                // Set event class for global event.
+                $events[$event->id]->class = 'calendar_event_global';
+            } else if ($event->courseid != 0 && $event->courseid != SITEID && $event->groupid == 0) {
+                $typesbyday[$eventdaystart]['startcourse'] = true;
+                // Set event class for course event.
+                $events[$event->id]->class = 'calendar_event_course';
+            } else if ($event->groupid) {
+                $typesbyday[$eventdaystart]['startgroup'] = true;
+                // Set event class for group event.
+                $events[$event->id]->class = 'calendar_event_group';
+            } else if ($event->userid) {
+                $typesbyday[$eventdaystart]['startuser'] = true;
+                // Set event class for user event.
+                $events[$event->id]->class = 'calendar_event_user';
+            }
+        }
+
+        if ($event->timeduration == 0) {
+            // Proceed with the next.
+            continue;
+        }
+
+        // The event starts on $month $year or before.
+        if ($startdate['mon'] == $month && $startdate['year'] == $year) {
+            $lowerbound = intval($startdate['mday']);
+        } else {
+            $lowerbound = 0;
+        }
+
+        // Also, it ends on $month $year or later.
+        if ($enddate['mon'] == $month && $enddate['year'] == $year) {
+            $upperbound = intval($enddate['mday']);
+        } else {
+            $upperbound = calendar_days_in_month($month, $year);
+        }
+
+        // Mark all days between $lowerbound and $upperbound (inclusive) as duration.
+        for ($i = $lowerbound + 1; $i <= $upperbound; ++$i) {
+            $durationbyday[$i][] = $event->id;
+            if ($event->courseid == SITEID && $event->groupid == 0) {
+                $typesbyday[$i]['durationglobal'] = true;
+            } else if ($event->courseid != 0 && $event->courseid != SITEID && $event->groupid == 0) {
+                $typesbyday[$i]['durationcourse'] = true;
+            } else if ($event->groupid) {
+                $typesbyday[$i]['durationgroup'] = true;
+            } else if ($event->userid) {
+                $typesbyday[$i]['durationuser'] = true;
+            }
+        }
+
+    }
+    return;
 }
 
 /**
@@ -1579,7 +2450,84 @@ function calendar_events_by_day($events, $month, $year, &$eventsbyday, &$duratio
  * @return array An array of courses, groups, and user to load calendar events for based upon filters
  */
 function calendar_set_filters(array $courseeventsfrom, $ignorefilters = false) {
-    return \core_calendar\api::set_filters($courseeventsfrom, $ignorefilters);
+    global $USER, $CFG;
+
+    // For backwards compatability we have to check whether the courses array contains
+    // just id's in which case we need to load course objects.
+    $coursestoload = array();
+    foreach ($courseeventsfrom as $id => $something) {
+        if (!is_object($something)) {
+            $coursestoload[] = $id;
+            unset($courseeventsfrom[$id]);
+        }
+    }
+
+    $courses = array();
+    $user = false;
+    $group = false;
+
+    // Get the capabilities that allow seeing group events from all groups.
+    $allgroupscaps = array('moodle/site:accessallgroups', 'moodle/calendar:manageentries');
+
+    $isloggedin = isloggedin();
+
+    if ($ignorefilters || calendar_show_event_type(CALENDAR_EVENT_COURSE)) {
+        $courses = array_keys($courseeventsfrom);
+    }
+    if ($ignorefilters || calendar_show_event_type(CALENDAR_EVENT_GLOBAL)) {
+        $courses[] = SITEID;
+    }
+    $courses = array_unique($courses);
+    sort($courses);
+
+    if (!empty($courses) && in_array(SITEID, $courses)) {
+        // Sort courses for consistent colour highlighting.
+        // Effectively ignoring SITEID as setting as last course id.
+        $key = array_search(SITEID, $courses);
+        unset($courses[$key]);
+        $courses[] = SITEID;
+    }
+
+    if ($ignorefilters || ($isloggedin && calendar_show_event_type(CALENDAR_EVENT_USER))) {
+        $user = $USER->id;
+    }
+
+    if (!empty($courseeventsfrom) && (calendar_show_event_type(CALENDAR_EVENT_GROUP) || $ignorefilters)) {
+
+        if (count($courseeventsfrom) == 1) {
+            $course = reset($courseeventsfrom);
+            if (has_any_capability($allgroupscaps, \context_course::instance($course->id))) {
+                $coursegroups = groups_get_all_groups($course->id, 0, 0, 'g.id');
+                $group = array_keys($coursegroups);
+            }
+        }
+        if ($group === false) {
+            if (!empty($CFG->calendar_adminseesall) && has_any_capability($allgroupscaps, \context_system::instance())) {
+                $group = true;
+            } else if ($isloggedin) {
+                $groupids = array();
+                foreach ($courseeventsfrom as $courseid => $course) {
+                    // If the user is an editing teacher in there.
+                    if (!empty($USER->groupmember[$course->id])) {
+                        // We've already cached the users groups for this course so we can just use that.
+                        $groupids = array_merge($groupids, $USER->groupmember[$course->id]);
+                    } else if ($course->groupmode != NOGROUPS || !$course->groupmodeforce) {
+                        // If this course has groups, show events from all of those related to the current user.
+                        $coursegroups = groups_get_user_groups($course->id, $USER->id);
+                        $groupids = array_merge($groupids, $coursegroups['0']);
+                    }
+                }
+                if (!empty($groupids)) {
+                    $group = $groupids;
+                }
+            }
+        }
+    }
+    if (empty($courses)) {
+        $courses = false;
+    }
+
+    return array($courses, $group, $user);
 }
 
 /**
@@ -1589,7 +2537,54 @@ function calendar_set_filters(array $courseeventsfrom, $ignorefilters = false) {
  * @return bool capability to edit event
  */
 function calendar_edit_event_allowed($event) {
-    return \core_calendar\api::can_edit_event($event);
+    global $USER, $DB;
+
+    // Must be logged in.
+    if (!isloggedin()) {
+        return false;
+    }
+
+    // Can not be using guest account.
+    if (isguestuser()) {
+        return false;
+    }
+
+    // You cannot edit URL based calendar subscription events presently.
+    if (!empty($event->subscriptionid)) {
+        if (!empty($event->subscription->url)) {
+            // This event can be updated externally, so it cannot be edited.
+            return false;
+        }
+    }
+
+    $sitecontext = \context_system::instance();
+
+    // If user has manageentries at site level, return true.
+    if (has_capability('moodle/calendar:manageentries', $sitecontext)) {
+        return true;
+    }
+
+    // If groupid is set, it's definitely a group event.
+    if (!empty($event->groupid)) {
+        // Allow users to add/edit group events if -
+        // 1) They have manageentries for the course OR
+        // 2) They have managegroupentries AND are in the group.
+        $group = $DB->get_record('groups', array('id' => $event->groupid));
+        return $group && (
+                has_capability('moodle/calendar:manageentries', $event->context) ||
+                (has_capability('moodle/calendar:managegroupentries', $event->context)
+                    && groups_is_member($event->groupid)));
+    } else if (!empty($event->courseid)) {
+        // If groupid is not set, but course is set, it's definiely a course event.
+        return has_capability('moodle/calendar:manageentries', $event->context);
+    } else if (!empty($event->userid) && $event->userid == $USER->id) {
+        // If course is not set, but userid id set, it's a user event.
+        return (has_capability('moodle/calendar:manageownentries', $event->context));
+    } else if (!empty($event->userid)) {
+        return (has_capability('moodle/calendar:manageentries', $event->context));
+    }
+
+    return false;
 }
 
 /**
@@ -1599,7 +2594,30 @@ function calendar_edit_event_allowed($event) {
  * @return array $courses Array of courses to display
  */
 function calendar_get_default_courses() {
-    return \core_calendar\api::get_default_courses();
+    global $CFG, $DB;
+
+    if (!isloggedin()) {
+        return array();
+    }
+
+    if (!empty($CFG->calendar_adminseesall) && has_capability('moodle/calendar:manageentries', \context_system::instance())) {
+        $select = ', ' . \context_helper::get_preload_record_columns_sql('ctx');
+        $join = "LEFT JOIN {context} ctx ON (ctx.instanceid = c.id AND ctx.contextlevel = :contextlevel)";
+        $sql = "SELECT c.* $select
+                      FROM {course} c
+                      $join
+                     WHERE EXISTS (SELECT 1 FROM {event} e WHERE e.courseid = c.id)
+                  ";
+        $courses = $DB->get_records_sql($sql, array('contextlevel' => CONTEXT_COURSE), 0, 20);
+        foreach ($courses as $course) {
+            \context_helper::preload_from_record($course);
+        }
+        return $courses;
+    }
+
+    $courses = enrol_get_my_courses();
+
+    return $courses;
 }
 
 /**
@@ -1613,7 +2631,84 @@ function calendar_get_default_courses() {
  * @return string $eventtime link/string for event time
  */
 function calendar_format_event_time($event, $now, $linkparams = null, $usecommonwords = true, $showtime = 0) {
-    return \core_calendar\api::get_format_event_time($event, $now, $linkparams, $usecommonwords, $showtime);
+    $starttime = $event->timestart;
+    $endtime = $event->timestart + $event->timeduration;
+
+    if (empty($linkparams) || !is_array($linkparams)) {
+        $linkparams = array();
+    }
+
+    $linkparams['view'] = 'day';
+
+    // OK, now to get a meaningful display.
+    // Check if there is a duration for this event.
+    if ($event->timeduration) {
+        // Get the midnight of the day the event will start.
+        $usermidnightstart = usergetmidnight($starttime);
+        // Get the midnight of the day the event will end.
+        $usermidnightend = usergetmidnight($endtime);
+        // Check if we will still be on the same day.
+        if ($usermidnightstart == $usermidnightend) {
+            // Check if we are running all day.
+            if ($event->timeduration == DAYSECS) {
+                $time = get_string('allday', 'calendar');
+            } else { // Specify the time we will be running this from.
+                $datestart = calendar_time_representation($starttime);
+                $dateend = calendar_time_representation($endtime);
+                $time = $datestart . ' <strong>&raquo;</strong> ' . $dateend;
+            }
+
+            // Set printable representation.
+            if (!$showtime) {
+                $day = calendar_day_representation($event->timestart, $now, $usecommonwords);
+                $url = calendar_get_link_href(new \moodle_url(CALENDAR_URL . 'view.php', $linkparams), 0, 0, 0, $endtime);
+                $eventtime = \html_writer::link($url, $day) . ', ' . $time;
+            } else {
+                $eventtime = $time;
+            }
+        } else { // It must spans two or more days.
+            $daystart = calendar_day_representation($event->timestart, $now, $usecommonwords) . ', ';
+            if ($showtime == $usermidnightstart) {
+                $daystart = '';
+            }
+            $timestart = calendar_time_representation($event->timestart);
+            $dayend = calendar_day_representation($event->timestart + $event->timeduration, $now, $usecommonwords) . ', ';
+            if ($showtime == $usermidnightend) {
+                $dayend = '';
+            }
+            $timeend = calendar_time_representation($event->timestart + $event->timeduration);
+
+            // Set printable representation.
+            if ($now >= $usermidnightstart && $now < strtotime('+1 day', $usermidnightstart)) {
+                $url = calendar_get_link_href(new \moodle_url(CALENDAR_URL . 'view.php', $linkparams), 0, 0, 0, $endtime);
+                $eventtime = $timestart . ' <strong>&raquo;</strong> ' . \html_writer::link($url, $dayend) . $timeend;
+            } else {
+                // The event is in the future, print start and end links.
+                $url = calendar_get_link_href(new \moodle_url(CALENDAR_URL . 'view.php', $linkparams), 0, 0, 0, $starttime);
+                $eventtime = \html_writer::link($url, $daystart) . $timestart . ' <strong>&raquo;</strong> ';
+
+                $url = calendar_get_link_href(new \moodle_url(CALENDAR_URL . 'view.php', $linkparams),  0, 0, 0, $endtime);
+                $eventtime .= \html_writer::link($url, $dayend) . $timeend;
+            }
+        }
+    } else { // There is no time duration.
+        $time = calendar_time_representation($event->timestart);
+        // Set printable representation.
+        if (!$showtime) {
+            $day = calendar_day_representation($event->timestart, $now, $usecommonwords);
+            $url = calendar_get_link_href(new \moodle_url(CALENDAR_URL . 'view.php', $linkparams),  0, 0, 0, $starttime);
+            $eventtime = \html_writer::link($url, $day) . ', ' . trim($time);
+        } else {
+            $eventtime = $time;
+        }
+    }
+
+    // Check if It has expired.
+    if ($event->timestart + $event->timeduration < $now) {
+        $eventtime = '<span class="dimmed_text">' . str_replace(' href=', ' class="dimmed" href=', $eventtime) . '</span>';
+    }
+
+    return $eventtime;
 }
 
 /**
@@ -1624,7 +2719,17 @@ function calendar_format_event_time($event, $now, $linkparams = null, $usecommon
  * @return bool True if the tyep should be displayed false otherwise
  */
 function calendar_show_event_type($type, $user = null) {
-    return \core_calendar\api::show_event_type($type, $user);
+    $default = CALENDAR_EVENT_GLOBAL + CALENDAR_EVENT_COURSE + CALENDAR_EVENT_GROUP + CALENDAR_EVENT_USER;
+
+    if (get_user_preferences('calendar_persistflt', 0, $user) === 0) {
+        global $SESSION;
+        if (!isset($SESSION->calendarshoweventtype)) {
+            $SESSION->calendarshoweventtype = $default;
+        }
+        return $SESSION->calendarshoweventtype & $type;
+    } else {
+        return get_user_preferences('calendar_savedflt', $default, $user) & $type;
+    }
 }
 
 /**
@@ -1639,7 +2744,35 @@ function calendar_show_event_type($type, $user = null) {
  * @param stdClass|int $user moodle user object or id, null means current user
  */
 function calendar_set_event_type_display($type, $display = null, $user = null) {
-    \core_calendar\api::set_event_type_display($type, $display, $user);
+    $persist = get_user_preferences('calendar_persistflt', 0, $user);
+    $default = CALENDAR_EVENT_GLOBAL + CALENDAR_EVENT_COURSE + CALENDAR_EVENT_GROUP + CALENDAR_EVENT_USER;
+    if ($persist === 0) {
+        global $SESSION;
+        if (!isset($SESSION->calendarshoweventtype)) {
+            $SESSION->calendarshoweventtype = $default;
+        }
+        $preference = $SESSION->calendarshoweventtype;
+    } else {
+        $preference = get_user_preferences('calendar_savedflt', $default, $user);
+    }
+    $current = $preference & $type;
+    if ($display === null) {
+        $display = !$current;
+    }
+    if ($display && !$current) {
+        $preference += $type;
+    } else if (!$display && $current) {
+        $preference -= $type;
+    }
+    if ($persist === 0) {
+        $SESSION->calendarshoweventtype = $preference;
+    } else {
+        if ($preference == $default) {
+            unset_user_preference('calendar_savedflt', $user);
+        } else {
+            set_user_preference('calendar_savedflt', $preference, $user);
+        }
+    }
 }
 
 /**
@@ -1649,7 +2782,43 @@ function calendar_set_event_type_display($type, $display = null, $user = null) {
  * @param stdClass|int $course object of a course or course id
  */
 function calendar_get_allowed_types(&$allowed, $course = null) {
-    \core_calendar\api::get_allowed_types($allowed, $course);
+    global $USER, $DB;
+
+    $allowed = new \stdClass();
+    $allowed->user = has_capability('moodle/calendar:manageownentries', \context_system::instance());
+    $allowed->groups = false;
+    $allowed->courses = false;
+    $allowed->site = has_capability('moodle/calendar:manageentries', \context_course::instance(SITEID));
+
+    if (!empty($course)) {
+        if (!is_object($course)) {
+            $course = $DB->get_record('course', array('id' => $course), '*', MUST_EXIST);
+        }
+        if ($course->id != SITEID) {
+            $coursecontext = \context_course::instance($course->id);
+            $allowed->user = has_capability('moodle/calendar:manageownentries', $coursecontext);
+
+            if (has_capability('moodle/calendar:manageentries', $coursecontext)) {
+                $allowed->courses = array($course->id => 1);
+
+                if ($course->groupmode != NOGROUPS || !$course->groupmodeforce) {
+                    if (has_capability('moodle/site:accessallgroups', $coursecontext)) {
+                        $allowed->groups = groups_get_all_groups($course->id);
+                    } else {
+                        $allowed->groups = groups_get_all_groups($course->id, $USER->id);
+                    }
+                }
+            } else if (has_capability('moodle/calendar:managegroupentries', $coursecontext)) {
+                if ($course->groupmode != NOGROUPS || !$course->groupmodeforce) {
+                    if (has_capability('moodle/site:accessallgroups', $coursecontext)) {
+                        $allowed->groups = groups_get_all_groups($course->id);
+                    } else {
+                        $allowed->groups = groups_get_all_groups($course->id, $USER->id);
+                    }
+                }
+            }
+        }
+    }
 }
 
 /**
@@ -1659,7 +2828,13 @@ function calendar_get_allowed_types(&$allowed, $course = null) {
  * @return bool has the capability to add at least one event type
  */
 function calendar_user_can_add_event($course) {
-    return \core_calendar\api::can_add_event_to_course($course);
+    if (!isloggedin() || isguestuser()) {
+        return false;
+    }
+
+    calendar_get_allowed_types($allowed, $course);
+
+    return (bool)($allowed->user || $allowed->groups || $allowed->courses || $allowed->site);
 }
 
 /**
@@ -1669,7 +2844,42 @@ function calendar_user_can_add_event($course) {
  * @return bool has the capability to add event
  */
 function calendar_add_event_allowed($event) {
-    return \core_calendar\api::can_add_event($event);
+    global $USER, $DB;
+
+    // Can not be using guest account.
+    if (!isloggedin() or isguestuser()) {
+        return false;
+    }
+
+    $sitecontext = \context_system::instance();
+
+    // If user has manageentries at site level, always return true.
+    if (has_capability('moodle/calendar:manageentries', $sitecontext)) {
+        return true;
+    }
+
+    switch ($event->eventtype) {
+        case 'course':
+            return has_capability('moodle/calendar:manageentries', $event->context);
+        case 'group':
+            // Allow users to add/edit group events if -
+            // 1) They have manageentries (= entries for whole course).
+            // 2) They have managegroupentries AND are in the group.
+            $group = $DB->get_record('groups', array('id' => $event->groupid));
+            return $group && (
+                    has_capability('moodle/calendar:manageentries', $event->context) ||
+                    (has_capability('moodle/calendar:managegroupentries', $event->context)
+                        && groups_is_member($event->groupid)));
+        case 'user':
+            if ($event->userid == $USER->id) {
+                return (has_capability('moodle/calendar:manageownentries', $event->context));
+            }
+        // There is intentionally no 'break'.
+        case 'site':
+            return has_capability('moodle/calendar:manageentries', $event->context);
+        default:
+            return has_capability('moodle/calendar:manageentries', $event->context);
+    }
 }
 
 /**
@@ -1678,7 +2888,14 @@ function calendar_add_event_allowed($event) {
  * @return array An array of poll interval options. Interval => description.
  */
 function calendar_get_pollinterval_choices() {
-    return \core_calendar\api::get_poll_interval_choices();
+    return array(
+        '0' => new \lang_string('never', 'calendar'),
+        HOURSECS => new \lang_string('hourly', 'calendar'),
+        DAYSECS => new \lang_string('daily', 'calendar'),
+        WEEKSECS => new \lang_string('weekly', 'calendar'),
+        '2628000' => new \lang_string('monthly', 'calendar'),
+        YEARSECS => new \lang_string('annually', 'calendar')
+    );
 }
 
 /**
@@ -1688,7 +2905,24 @@ function calendar_get_pollinterval_choices() {
  * @return array An array containing the event types the user can create.
  */
 function calendar_get_eventtype_choices($courseid) {
-    return \core_calendar\api::get_event_type_choices($courseid);
+    $choices = array();
+    $allowed = new \stdClass;
+    calendar_get_allowed_types($allowed, $courseid);
+
+    if ($allowed->user) {
+        $choices['user'] = get_string('userevents', 'calendar');
+    }
+    if ($allowed->site) {
+        $choices['site'] = get_string('siteevents', 'calendar');
+    }
+    if (!empty($allowed->courses)) {
+        $choices['course'] = get_string('courseevents', 'calendar');
+    }
+    if (!empty($allowed->groups) and is_array($allowed->groups)) {
+        $choices['group'] = get_string('group');
+    }
+
+    return array($choices, $allowed->groups);
 }
 
 /**
@@ -1698,7 +2932,44 @@ function calendar_get_eventtype_choices($courseid) {
  * @return int The insert ID, if any.
  */
 function calendar_add_subscription($sub) {
-    return \core_calendar\api::add_subscription($sub);
+    global $DB, $USER, $SITE;
+
+    if ($sub->eventtype === 'site') {
+        $sub->courseid = $SITE->id;
+    } else if ($sub->eventtype === 'group' || $sub->eventtype === 'course') {
+        $sub->courseid = $sub->course;
+    } else {
+        // User events.
+        $sub->courseid = 0;
+    }
+    $sub->userid = $USER->id;
+
+    // File subscriptions never update.
+    if (empty($sub->url)) {
+        $sub->pollinterval = 0;
+    }
+
+    if (!empty($sub->name)) {
+        if (empty($sub->id)) {
+            $id = $DB->insert_record('event_subscriptions', $sub);
+            // We cannot cache the data here because $sub is not complete.
+            $sub->id = $id;
+            // Trigger event, calendar subscription added.
+            $eventparams = array('objectid' => $sub->id,
+                'context' => calendar_get_calendar_context($sub),
+                'other' => array('eventtype' => $sub->eventtype, 'courseid' => $sub->courseid)
+            );
+            $event = \core\event\calendar_subscription_created::create($eventparams);
+            $event->trigger();
+            return $id;
+        } else {
+            // Why are we doing an update here?
+            calendar_update_subscription($sub);
+            return $sub->id;
+        }
+    } else {
+        print_error('errorbadsubscription', 'importcalendar');
+    }
 }
 
 /**
@@ -1712,7 +2983,99 @@ function calendar_add_subscription($sub) {
  * @return int Code: CALENDAR_IMPORT_EVENT_UPDATED = updated,  CALENDAR_IMPORT_EVENT_INSERTED = inserted, 0 = error
  */
 function calendar_add_icalendar_event($event, $courseid, $subscriptionid, $timezone='UTC') {
-    return \core_calendar\api::add_icalendar_event($event, $courseid, $subscriptionid, $timezone);
+    global $DB;
+
+    // Probably an unsupported X-MICROSOFT-CDO-BUSYSTATUS event.
+    if (empty($event->properties['SUMMARY'])) {
+        return 0;
+    }
+
+    $name = $event->properties['SUMMARY'][0]->value;
+    $name = str_replace('\n', '<br />', $name);
+    $name = str_replace('\\', '', $name);
+    $name = preg_replace('/\s+/u', ' ', $name);
+
+    $eventrecord = new \stdClass;
+    $eventrecord->name = clean_param($name, PARAM_NOTAGS);
+
+    if (empty($event->properties['DESCRIPTION'][0]->value)) {
+        $description = '';
+    } else {
+        $description = $event->properties['DESCRIPTION'][0]->value;
+        $description = clean_param($description, PARAM_NOTAGS);
+        $description = str_replace('\n', '<br />', $description);
+        $description = str_replace('\\', '', $description);
+        $description = preg_replace('/\s+/u', ' ', $description);
+    }
+    $eventrecord->description = $description;
+
+    // Probably a repeating event with RRULE etc. TODO: skip for now.
+    if (empty($event->properties['DTSTART'][0]->value)) {
+        return 0;
+    }
+
+    if (isset($event->properties['DTSTART'][0]->parameters['TZID'])) {
+        $tz = $event->properties['DTSTART'][0]->parameters['TZID'];
+    } else {
+        $tz = $timezone;
+    }
+    $tz = \core_date::normalise_timezone($tz);
+    $eventrecord->timestart = strtotime($event->properties['DTSTART'][0]->value . ' ' . $tz);
+    if (empty($event->properties['DTEND'])) {
+        $eventrecord->timeduration = 0; // No duration if no end time specified.
+    } else {
+        if (isset($event->properties['DTEND'][0]->parameters['TZID'])) {
+            $endtz = $event->properties['DTEND'][0]->parameters['TZID'];
+        } else {
+            $endtz = $timezone;
+        }
+        $endtz = \core_date::normalise_timezone($endtz);
+        $eventrecord->timeduration = strtotime($event->properties['DTEND'][0]->value . ' ' . $endtz) - $eventrecord->timestart;
+    }
+
+    // Check to see if it should be treated as an all day event.
+    if ($eventrecord->timeduration == DAYSECS) {
+        // Check to see if the event started at Midnight on the imported calendar.
+        date_default_timezone_set($timezone);
+        if (date('H:i:s', $eventrecord->timestart) === "00:00:00") {
+            // This event should be an all day event.
+            $eventrecord->timeduration = 0;
+        }
+        \core_date::set_default_server_timezone();
+    }
+
+    $eventrecord->uuid = $event->properties['UID'][0]->value;
+    $eventrecord->timemodified = time();
+
+    // Add the iCal subscription details if required.
+    // We should never do anything with an event without a subscription reference.
+    $sub = calendar_get_subscription($subscriptionid);
+    $eventrecord->subscriptionid = $subscriptionid;
+    $eventrecord->userid = $sub->userid;
+    $eventrecord->groupid = $sub->groupid;
+    $eventrecord->courseid = $sub->courseid;
+    $eventrecord->eventtype = $sub->eventtype;
+
+    if ($updaterecord = $DB->get_record('event', array('uuid' => $eventrecord->uuid,
+        'subscriptionid' => $eventrecord->subscriptionid))) {
+        $eventrecord->id = $updaterecord->id;
+        $return = CALENDAR_IMPORT_EVENT_UPDATED; // Update.
+    } else {
+        $return = CALENDAR_IMPORT_EVENT_INSERTED; // Insert.
+    }
+    if ($createdevent = \calendar_event::create($eventrecord, false)) {
+        if (!empty($event->properties['RRULE'])) {
+            // Repeating events.
+            date_default_timezone_set($tz); // Change time zone to parse all events.
+            $rrule = new rrule_manager($event->properties['RRULE'][0]->value);
+            $rrule->parse_rrule();
+            $rrule->create_events($createdevent);
+            \core_date::set_default_server_timezone(); // Change time zone back to what it was.
+        }
+        return $return;
+    } else {
+        return 0;
+    }
 }
 
 /**
@@ -1725,7 +3088,30 @@ function calendar_add_icalendar_event($event, $courseid, $subscriptionid, $timez
  * @return string A log of the import progress, including errors
  */
 function calendar_process_subscription_row($subscriptionid, $pollinterval, $action) {
-    return \core_calendar\api::process_subscription_row($subscriptionid, $pollinterval, $action);
+    // Fetch the subscription from the database making sure it exists.
+    $sub = calendar_get_subscription($subscriptionid);
+
+    // Update or remove the subscription, based on action.
+    switch ($action) {
+        case CALENDAR_SUBSCRIPTION_UPDATE:
+            // Skip updating file subscriptions.
+            if (empty($sub->url)) {
+                break;
+            }
+            $sub->pollinterval = $pollinterval;
+            calendar_update_subscription($sub);
+
+            // Update the events.
+            return "<p>" . get_string('subscriptionupdated', 'calendar', $sub->name) . "</p>" .
+                calendar_update_subscription_events($subscriptionid);
+        case CALENDAR_SUBSCRIPTION_REMOVE:
+            calendar_delete_subscription($subscriptionid);
+            return get_string('subscriptionremoved', 'calendar', $sub->name);
+            break;
+        default:
+            break;
+    }
+    return '';
 }
 
 /**
@@ -1734,7 +3120,24 @@ function calendar_process_subscription_row($subscriptionid, $pollinterval, $acti
  * @param int|stdClass $subscription subscription or it's id, which needs to be deleted.
  */
 function calendar_delete_subscription($subscription) {
-    \core_calendar\api::delete_subscription($subscription);
+    global $DB;
+
+    if (!is_object($subscription)) {
+        $subscription = $DB->get_record('event_subscriptions', array('id' => $subscription), '*', MUST_EXIST);
+    }
+
+    // Delete subscription and related events.
+    $DB->delete_records('event', array('subscriptionid' => $subscription->id));
+    $DB->delete_records('event_subscriptions', array('id' => $subscription->id));
+    \cache_helper::invalidate_by_definition('core', 'calendar_subscriptions', array(), array($subscription->id));
+
+    // Trigger event, calendar subscription deleted.
+    $eventparams = array('objectid' => $subscription->id,
+        'context' => calendar_get_calendar_context($subscription),
+        'other' => array('courseid' => $subscription->courseid)
+    );
+    $event = \core\event\calendar_subscription_deleted::create($eventparams);
+    $event->trigger();
 }
 
 /**
@@ -1744,7 +3147,23 @@ function calendar_delete_subscription($subscription) {
  * @return iCalendar The iCalendar object
  */
 function calendar_get_icalendar($url) {
-    return \core_calendar\api::get_icalendar($url);
+    global $CFG;
+
+    require_once($CFG->libdir . '/filelib.php');
+
+    $curl = new \curl();
+    $curl->setopt(array('CURLOPT_FOLLOWLOCATION' => 1, 'CURLOPT_MAXREDIRS' => 5));
+    $calendar = $curl->get($url);
+
+    // Http code validation should actually be the job of curl class.
+    if (!$calendar || $curl->info['http_code'] != 200 || !empty($curl->errorno)) {
+        throw new \moodle_exception('errorinvalidicalurl', 'calendar');
+    }
+
+    $ical = new \iCalendar();
+    $ical->unserialize($calendar);
+
+    return $ical;
 }
 
 /**
@@ -1756,7 +3175,65 @@ function calendar_get_icalendar($url) {
  * @return string A log of the import progress, including errors.
  */
 function calendar_import_icalendar_events($ical, $courseid, $subscriptionid = null) {
-    return \core_calendar\api::import_icalendar_events($ical, $courseid, $subscriptionid);
+    global $DB;
+
+    $return = '';
+    $eventcount = 0;
+    $updatecount = 0;
+
+    // Large calendars take a while...
+    if (!CLI_SCRIPT) {
+        \core_php_time_limit::raise(300);
+    }
+
+    // Mark all events in a subscription with a zero timestamp.
+    if (!empty($subscriptionid)) {
+        $sql = "UPDATE {event} SET timemodified = :time WHERE subscriptionid = :id";
+        $DB->execute($sql, array('time' => 0, 'id' => $subscriptionid));
+    }
+
+    // Grab the timezone from the iCalendar file to be used later.
+    if (isset($ical->properties['X-WR-TIMEZONE'][0]->value)) {
+        $timezone = $ical->properties['X-WR-TIMEZONE'][0]->value;
+    } else {
+        $timezone = 'UTC';
+    }
+
+    $return = '';
+    foreach ($ical->components['VEVENT'] as $event) {
+        $res = calendar_add_icalendar_event($event, $courseid, $subscriptionid, $timezone);
+        switch ($res) {
+            case CALENDAR_IMPORT_EVENT_UPDATED:
+                $updatecount++;
+                break;
+            case CALENDAR_IMPORT_EVENT_INSERTED:
+                $eventcount++;
+                break;
+            case 0:
+                $return .= '<p>' . get_string('erroraddingevent', 'calendar') . ': ';
+                if (empty($event->properties['SUMMARY'])) {
+                    $return .= '(' . get_string('notitle', 'calendar') . ')';
+                } else {
+                    $return .= $event->properties['SUMMARY'][0]->value;
+                }
+                $return .= "</p>\n";
+                break;
+        }
+    }
+
+    $return .= "<p>" . get_string('eventsimported', 'calendar', $eventcount) . "</p> ";
+    $return .= "<p>" . get_string('eventsupdated', 'calendar', $updatecount) . "</p>";
+
+    // Delete remaining zero-marked events since they're not in remote calendar.
+    if (!empty($subscriptionid)) {
+        $deletecount = $DB->count_records('event', array('timemodified' => 0, 'subscriptionid' => $subscriptionid));
+        if (!empty($deletecount)) {
+            $DB->delete_records('event', array('timemodified' => 0, 'subscriptionid' => $subscriptionid));
+            $return .= "<p> " . get_string('eventsdeleted', 'calendar') . ": {$deletecount} </p>\n";
+        }
+    }
+
+    return $return;
 }
 
 /**
@@ -1766,7 +3243,20 @@ function calendar_import_icalendar_events($ical, $courseid, $subscriptionid = nu
  * @return string A log of the import progress, including errors.
  */
 function calendar_update_subscription_events($subscriptionid) {
-    return \core_calendar\api::update_subscription_events($subscriptionid);
+    $sub = calendar_get_subscription($subscriptionid);
+
+    // Don't update a file subscription.
+    if (empty($sub->url)) {
+        return 'File subscription not updated.';
+    }
+
+    $ical = calendar_get_icalendar($sub->url);
+    $return = calendar_import_icalendar_events($ical, $sub->courseid, $subscriptionid);
+    $sub->lastupdated = time();
+
+    calendar_update_subscription($sub);
+
+    return $return;
 }
 
 /**
@@ -1777,7 +3267,29 @@ function calendar_update_subscription_events($subscriptionid) {
  * @since Moodle 2.5
  */
 function calendar_update_subscription($subscription) {
-    \core_calendar\api::update_subscription($subscription);
+    global $DB;
+
+    if (is_array($subscription)) {
+        $subscription = (object)$subscription;
+    }
+    if (empty($subscription->id) || !$DB->record_exists('event_subscriptions', array('id' => $subscription->id))) {
+        throw new \coding_exception('Cannot update a subscription without a valid id');
+    }
+
+    $DB->update_record('event_subscriptions', $subscription);
+
+    // Update cache.
+    $cache = \cache::make('core', 'calendar_subscriptions');
+    $cache->set($subscription->id, $subscription);
+
+    // Trigger event, calendar subscription updated.
+    $eventparams = array('userid' => $subscription->userid,
+        'objectid' => $subscription->id,
+        'context' => calendar_get_calendar_context($subscription),
+        'other' => array('eventtype' => $subscription->eventtype, 'courseid' => $subscription->courseid)
+    );
+    $event = \core\event\calendar_subscription_updated::create($eventparams);
+    $event->trigger();
 }
 
 /**
@@ -1787,7 +3299,39 @@ function calendar_update_subscription($subscription) {
  * @return bool true if current user can edit the subscription else false
  */
 function calendar_can_edit_subscription($subscriptionorid) {
-    return \core_calendar\api::can_edit_subscription($subscriptionorid);
+    if (is_array($subscriptionorid)) {
+        $subscription = (object)$subscriptionorid;
+    } else if (is_object($subscriptionorid)) {
+        $subscription = $subscriptionorid;
+    } else {
+        $subscription = calendar_get_subscription($subscriptionorid);
+    }
+
+    $allowed = new \stdClass;
+    $courseid = $subscription->courseid;
+    $groupid = $subscription->groupid;
+
+    calendar_get_allowed_types($allowed, $courseid);
+    switch ($subscription->eventtype) {
+        case 'user':
+            return $allowed->user;
+        case 'course':
+            if (isset($allowed->courses[$courseid])) {
+                return $allowed->courses[$courseid];
+            } else {
+                return false;
+            }
+        case 'site':
+            return $allowed->site;
+        case 'group':
+            if (isset($allowed->groups[$groupid])) {
+                return $allowed->groups[$groupid];
+            } else {
+                return false;
+            }
+        default:
+            return false;
+    }
 }
 
 /**
@@ -1798,7 +3342,15 @@ function calendar_can_edit_subscription($subscriptionorid) {
  * @return context instance
  */
 function calendar_get_calendar_context($subscription) {
-    return \core_calendar\api::get_calendar_context($subscription);
+    // Determine context based on calendar type.
+    if ($subscription->eventtype === 'site') {
+        $context = \context_course::instance(SITEID);
+    } else if ($subscription->eventtype === 'group' || $subscription->eventtype === 'course') {
+        $context = \context_course::instance($subscription->courseid);
+    } else {
+        $context = \context_user::instance($subscription->userid);
+    }
+    return $context;
 }
 
 /**
index 91dea50..3e4e0e9 100644 (file)
@@ -49,10 +49,10 @@ if ($courseid != SITEID && !empty($courseid)) {
     $courses = array($course->id => $course);
 } else {
     $course = get_site();
-    $courses = \core_calendar\api::get_default_courses();
+    $courses = calendar_get_default_courses();
 }
 require_course_login($course);
-if (!\core_calendar\api::can_add_event_to_course($course)) {
+if (!calendar_user_can_add_event($course)) {
     print_error('errorcannotimport', 'calendar');
 }
 
@@ -66,20 +66,20 @@ $importresults = '';
 $formdata = $form->get_data();
 if (!empty($formdata)) {
     require_sesskey(); // Must have sesskey for all actions.
-    $subscriptionid = \core_calendar\api::add_subscription($formdata);
+    $subscriptionid = calendar_add_subscription($formdata);
     if ($formdata->importfrom == CALENDAR_IMPORT_FROM_FILE) {
         // Blank the URL if it's a file import.
         $formdata->url = '';
         $calendar = $form->get_file_content('importfile');
         $ical = new iCalendar();
         $ical->unserialize($calendar);
-        $importresults = \core_calendar\api::import_icalendar_events($ical, $courseid, $subscriptionid);
+        $importresults = calendar_import_icalendar_events($ical, $courseid, $subscriptionid);
     } else {
         try {
-            $importresults = \core_calendar\api::update_subscription_events($subscriptionid);
+            $importresults = calendar_update_subscription_events($subscriptionid);
         } catch (moodle_exception $e) {
             // Delete newly added subscription and show invalid url error.
-            \core_calendar\api::delete_subscription($subscriptionid);
+            calendar_delete_subscription($subscriptionid);
             print_error($e->errorcode, $e->module, $PAGE->url);
         }
     }
@@ -88,9 +88,9 @@ if (!empty($formdata)) {
 } else if (!empty($subscriptionid)) {
     // The user is wanting to perform an action upon an existing subscription.
     require_sesskey(); // Must have sesskey for all actions.
-    if (\core_calendar\api::can_edit_subscription($subscriptionid)) {
+    if (calendar_can_edit_subscription($subscriptionid)) {
         try {
-            $importresults = \core_calendar\api::process_subscription_row($subscriptionid, $pollinterval, $action);
+            $importresults = calendar_process_subscription_row($subscriptionid, $pollinterval, $action);
         } catch (moodle_exception $e) {
             // If exception caught, then user should be redirected to page where he/she came from.
             print_error($e->errorcode, $e->module, $PAGE->url);
@@ -117,7 +117,7 @@ echo $OUTPUT->header();
 
 // Filter subscriptions which user can't edit.
 foreach($subscriptions as $subscription) {
-    if (!\core_calendar\api::can_edit_subscription($subscription)) {
+    if (!calendar_can_edit_subscription($subscription)) {
         unset($subscriptions[$subscription->id]);
     }
 }
index ea2df71..12ab3ac 100644 (file)
@@ -63,7 +63,7 @@ class calendar_addsubscription_form extends moodleform {
         $mform->setForceLtr('url');
 
         // Poll interval
-        $choices = \core_calendar\api::get_poll_interval_choices();
+        $choices = calendar_get_pollinterval_choices();
         $mform->addElement('select', 'pollinterval', get_string('pollinterval', 'calendar'), $choices);
         $mform->setDefault('pollinterval', 604800);
         $mform->addHelpButton('pollinterval', 'pollinterval', 'calendar');
@@ -78,7 +78,7 @@ class calendar_addsubscription_form extends moodleform {
         $mform->disabledIf('importfile', 'importfrom', 'eq', CALENDAR_IMPORT_FROM_URL);
 
         // Eventtype: 0 = user, 1 = global, anything else = course ID.
-        list($choices, $groups) = \core_calendar\api::get_event_type_choices($courseid);
+        list($choices, $groups) = calendar_get_eventtype_choices($courseid);
         $mform->addElement('select', 'eventtype', get_string('eventkind', 'calendar'), $choices);
         $mform->addRule('eventtype', get_string('required'), 'required');
         $mform->setType('eventtype', PARAM_ALPHA);
index 3b22819..ec209c3 100644 (file)
@@ -64,7 +64,7 @@ class core_calendar_renderer extends plugin_renderer_base {
     public function fake_block_filters($courseid, $day, $month, $year, $view, $courses) {
         $returnurl = $this->page->url;
         $returnurl->param('course', $courseid);
-        return html_writer::tag('div', \core_calendar\api::get_filter_controls($returnurl),
+        return html_writer::tag('div', calendar_filter_controls($returnurl),
             array('class' => 'calendar_filters filters'));
     }
 
@@ -82,26 +82,26 @@ class core_calendar_renderer extends plugin_renderer_base {
 
         $date = $calendartype->timestamp_to_date_array($calendar->time);
 
-        $prevmonth = \core_calendar\api::get_prev_month($date['mon'], $date['year']);
+        $prevmonth = calendar_sub_month($date['mon'], $date['year']);
         $prevmonthtime = $calendartype->convert_to_gregorian($prevmonth[1], $prevmonth[0], 1);
         $prevmonthtime = make_timestamp($prevmonthtime['year'], $prevmonthtime['month'], $prevmonthtime['day'],
             $prevmonthtime['hour'], $prevmonthtime['minute']);
 
-        $nextmonth = \core_calendar\api::get_next_month($date['mon'], $date['year']);
+        $nextmonth = calendar_add_month($date['mon'], $date['year']);
         $nextmonthtime = $calendartype->convert_to_gregorian($nextmonth[1], $nextmonth[0], 1);
         $nextmonthtime = make_timestamp($nextmonthtime['year'], $nextmonthtime['month'], $nextmonthtime['day'],
             $nextmonthtime['hour'], $nextmonthtime['minute']);
 
         $content  = html_writer::start_tag('div', array('class' => 'minicalendarblock'));
-        $content .= \core_calendar\api::get_mini_calendar($calendar->courses, $calendar->groups, $calendar->users,
+        $content .= calendar_get_mini($calendar->courses, $calendar->groups, $calendar->users,
             false, false, 'display', $calendar->courseid, $prevmonthtime);
         $content .= html_writer::end_tag('div');
         $content .= html_writer::start_tag('div', array('class' => 'minicalendarblock'));
-        $content .= \core_calendar\api::get_mini_calendar($calendar->courses, $calendar->groups, $calendar->users,
+        $content .= calendar_get_mini($calendar->courses, $calendar->groups, $calendar->users,
             false, false, 'display', $calendar->courseid, $calendar->time);
         $content .= html_writer::end_tag('div');
         $content .= html_writer::start_tag('div', array('class' => 'minicalendarblock'));
-        $content .= \core_calendar\api::get_mini_calendar($calendar->courses, $calendar->groups, $calendar->users,
+        $content .= calendar_get_mini($calendar->courses, $calendar->groups, $calendar->users,
             false, false, 'display', $calendar->courseid, $nextmonthtime);
         $content .= html_writer::end_tag('div');
         return $content;
@@ -168,17 +168,17 @@ class core_calendar_renderer extends plugin_renderer_base {
             $returnurl = $this->page->url;
         }
 
-        $events = \core_calendar\api::get_upcoming($calendar->courses, $calendar->groups, $calendar->users,
+        $events = calendar_get_upcoming($calendar->courses, $calendar->groups, $calendar->users,
             1, 100, $calendar->timestamp_today());
 
         $output  = html_writer::start_tag('div', array('class'=>'header'));
         $output .= $this->course_filter_selector($returnurl, get_string('dayviewfor', 'calendar'));
-        if (\core_calendar\api::can_add_event_to_course($calendar->course)) {
+        if (calendar_user_can_add_event($calendar->course)) {
             $output .= $this->add_event_button($calendar->course->id, 0, 0, 0, $calendar->time);
         }
         $output .= html_writer::end_tag('div');
         // Controls
-        $output .= html_writer::tag('div', \core_calendar\api::get_top_controls('day', array('id' => $calendar->courseid,
+        $output .= html_writer::tag('div', calendar_top_controls('day', array('id' => $calendar->courseid,
             'time' => $calendar->time)), array('class' => 'controls'));
 
         if (empty($events)) {
@@ -192,7 +192,7 @@ class core_calendar_renderer extends plugin_renderer_base {
                 $event = new calendar_event($event);
                 $event->calendarcourseid = $calendar->courseid;
                 if ($event->timestart >= $calendar->timestamp_today() && $event->timestart <= $calendar->timestamp_tomorrow()-1) {  // Print it now
-                    $event->time = \core_calendar\api::get_format_event_time($event, time(), null, false,
+                    $event->time = calendar_format_event_time($event, time(), null, false,
                         $calendar->timestamp_today());
                     $output .= $this->event($event);
                 } else {                                                                 // Save this for later
@@ -205,7 +205,7 @@ class core_calendar_renderer extends plugin_renderer_base {
                 $output .= html_writer::span(get_string('spanningevents', 'calendar'),
                     'calendar-information calendar-span-multiple-days');
                 foreach ($underway as $event) {
-                    $event->time = \core_calendar\api::get_format_event_time($event, time(), null, false,
+                    $event->time = calendar_format_event_time($event, time(), null, false,
                         $calendar->timestamp_today());
                     $output .= $this->event($event);
                 }
@@ -227,12 +227,12 @@ class core_calendar_renderer extends plugin_renderer_base {
     public function event(calendar_event $event, $showactions=true) {
         global $CFG;
 
-        $event = \core_calendar\api::add_event_metadata($event);
+        $event = calendar_add_event_metadata($event);
         $context = $event->context;
         $output = '';
 
         $output .= $this->output->box_start('card-header clearfix');
-        if (\core_calendar\api::can_edit_event($event) && $showactions) {
+        if (calendar_edit_event_allowed($event) && $showactions) {
             if (empty($event->cmid)) {
                 $editlink = new moodle_url(CALENDAR_URL.'event.php', array('action' => 'edit', 'id' => $event->id));
                 $deletelink = new moodle_url(CALENDAR_URL.'delete.php', array('id' => $event->id));
@@ -289,7 +289,7 @@ class core_calendar_renderer extends plugin_renderer_base {
             $output .= html_writer::tag('span', $event->time, array('class' => 'date pull-xs-right m-r-1'));
         } else {
             $attrs = array('class' => 'date pull-xs-right m-r-1');
-            $output .= html_writer::tag('span', \core_calendar\api::get_time_representation($event->timestart), $attrs);
+            $output .= html_writer::tag('span', calendar_time_representation($event->timestart), $attrs);
         }
         if (!empty($event->courselink)) {
             $output .= html_writer::tag('div', $event->courselink, array('class' => 'course'));
@@ -352,13 +352,13 @@ class core_calendar_renderer extends plugin_renderer_base {
         // Get the starting week day for this month.
         $startwday = dayofweek(1, $date['mon'], $date['year']);
         // Get the days in a week.
-        $daynames = \core_calendar\api::get_days();
+        $daynames = calendar_get_days();
         // Store the number of days in a week.
         $numberofdaysinweek = $calendartype->get_num_weekdays();
 
-        $display->minwday = \core_calendar\api::get_starting_weekday();
+        $display->minwday = calendar_get_starting_weekday();
         $display->maxwday = $display->minwday + ($numberofdaysinweek - 1);
-        $display->maxdays = \core_calendar\api::get_days_in_month($date['mon'], $date['year']);
+        $display->maxdays = calendar_days_in_month($date['mon'], $date['year']);
 
         // These are used for DB queries, so we want unixtime, so we need to use Gregorian dates.
         $display->tstart = make_timestamp($gy, $gm, $gd, $gh, $gmin, 0);
@@ -371,7 +371,7 @@ class core_calendar_renderer extends plugin_renderer_base {
         }
 
         // Get events from database
-        $events = \core_calendar\api::get_events($display->tstart, $display->tend, $calendar->users, $calendar->groups,
+        $events = calendar_get_events($display->tstart, $display->tend, $calendar->users, $calendar->groups,
             $calendar->courses);
         if (!empty($events)) {
             foreach($events as $eventid => $event) {
@@ -386,17 +386,17 @@ class core_calendar_renderer extends plugin_renderer_base {
         }
 
         // Extract information: events vs. time
-        \core_calendar\api::get_events_by_day($events, $date['mon'], $date['year'], $eventsbyday, $durationbyday,
+        calendar_events_by_day($events, $date['mon'], $date['year'], $eventsbyday, $durationbyday,
             $typesbyday, $calendar->courses);
 
         $output  = html_writer::start_tag('div', array('class'=>'header'));
         $output .= $this->course_filter_selector($returnurl, get_string('detailedmonthviewfor', 'calendar'));
-        if (\core_calendar\api::can_add_event_to_course($calendar->course)) {
+        if (calendar_user_can_add_event($calendar->course)) {
             $output .= $this->add_event_button($calendar->course->id, 0, 0, 0, $calendar->time);
         }
         $output .= html_writer::end_tag('div', array('class'=>'header'));
         // Controls
-        $output .= html_writer::tag('div', \core_calendar\api::get_top_controls('month', array('id' => $calendar->courseid,
+        $output .= html_writer::tag('div', calendar_top_controls('month', array('id' => $calendar->courseid,
             'time' => $calendar->time)), array('class' => 'controls'));
 
         $table = new html_table();
@@ -443,7 +443,7 @@ class core_calendar_renderer extends plugin_renderer_base {
 
             // Reset vars
             $cell = new html_table_cell();
-            $dayhref = \core_calendar\api::get_link_href(new moodle_url(CALENDAR_URL . 'view.php',
+            $dayhref = calendar_get_link_href(new moodle_url(CALENDAR_URL . 'view.php',
                 array('view' => 'day', 'course' => $calendar->courseid)), 0, 0, 0, $daytime);
 
             $cellclasses = array();
@@ -539,12 +539,12 @@ class core_calendar_renderer extends plugin_renderer_base {
             $returnurl = $this->page->url;
         }
 
-        $events = \core_calendar\api::get_upcoming($calendar->courses, $calendar->groups, $calendar->users,
+        $events = calendar_get_upcoming($calendar->courses, $calendar->groups, $calendar->users,
             $futuredays, $maxevents);
 
         $output  = html_writer::start_tag('div', array('class'=>'header'));
         $output .= $this->course_filter_selector($returnurl, get_string('upcomingeventsfor', 'calendar'));
-        if (\core_calendar\api::can_add_event_to_course($calendar->course)) {
+        if (calendar_user_can_add_event($calendar->course)) {
             $output .= $this->add_event_button($calendar->course->id);
         }
         $output .= html_writer::end_tag('div');
@@ -686,7 +686,7 @@ class core_calendar_renderer extends plugin_renderer_base {
             // Assemble pollinterval control.
             $html .= html_writer::start_tag('div', array('style' => 'float:left;'));
             $html .= html_writer::start_tag('select', array('name' => 'pollinterval', 'class' => 'custom-select'));
-            foreach (\core_calendar\api::get_poll_interval_choices() as $k => $v) {
+            foreach (calendar_get_pollinterval_choices() as $k => $v) {
                 $attributes = array();
                 if ($k == $subscription->pollinterval) {
                     $attributes['selected'] = 'selected';
index a25853d..c69de93 100644 (file)
@@ -44,16 +44,16 @@ $PAGE->set_context(context_system::instance());
 
 switch($var) {
     case 'showgroups':
-        \core_calendar\api::set_event_type_display(CALENDAR_EVENT_GROUP);
+        calendar_set_event_type_display(CALENDAR_EVENT_GROUP);
         break;
     case 'showcourses':
-        \core_calendar\api::set_event_type_display(CALENDAR_EVENT_COURSE);
+        calendar_set_event_type_display(CALENDAR_EVENT_COURSE);
         break;
     case 'showglobal':
-        \core_calendar\api::set_event_type_display(CALENDAR_EVENT_GLOBAL);
+        calendar_set_event_type_display(CALENDAR_EVENT_GLOBAL);
         break;
     case 'showuser':
-        \core_calendar\api::set_event_type_display(CALENDAR_EVENT_USER);
+        calendar_set_event_type_display(CALENDAR_EVENT_USER);
         break;
 }
 
index 7b2eaff..aaa3631 100644 (file)
@@ -44,357 +44,6 @@ class core_calendar_api_testcase extends advanced_testcase {
         $this->resetAfterTest();
     }
 
-    public function test_get_course_cached() {
-        // Setup some test courses.
-        $course1 = $this->getDataGenerator()->create_course();
-        $course2 = $this->getDataGenerator()->create_course();
-        $course3 = $this->getDataGenerator()->create_course();
-
-        // Load courses into cache.
-        $coursecache = null;
-        \core_calendar\api::get_course_cached($coursecache, $course1->id);
-        \core_calendar\api::get_course_cached($coursecache, $course2->id);
-        \core_calendar\api::get_course_cached($coursecache, $course3->id);
-
-        // Verify the cache.
-        $this->assertArrayHasKey($course1->id, $coursecache);
-        $cachedcourse1 = $coursecache[$course1->id];
-        $this->assertEquals($course1->id, $cachedcourse1->id);
-        $this->assertEquals($course1->shortname, $cachedcourse1->shortname);
-        $this->assertEquals($course1->fullname, $cachedcourse1->fullname);
-
-        $this->assertArrayHasKey($course2->id, $coursecache);
-        $cachedcourse2 = $coursecache[$course2->id];
-        $this->assertEquals($course2->id, $cachedcourse2->id);
-        $this->assertEquals($course2->shortname, $cachedcourse2->shortname);
-        $this->assertEquals($course2->fullname, $cachedcourse2->fullname);
-
-        $this->assertArrayHasKey($course3->id, $coursecache);
-        $cachedcourse3 = $coursecache[$course3->id];
-        $this->assertEquals($course3->id, $cachedcourse3->id);
-        $this->assertEquals($course3->shortname, $cachedcourse3->shortname);
-        $this->assertEquals($course3->fullname, $cachedcourse3->fullname);
-    }
-
-    /**
-     * Test that the get_events() function only returns activity events that are enabled.
-     */
-    public function test_get_events_with_disabled_module() {
-        global $DB;
-        $this->setAdminUser();
-        $generator = $this->getDataGenerator();
-        $course = $generator->create_course();
-        $assigngenerator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
-        $assigninstance = $assigngenerator->create_instance(['course' => $course->id]);
-        $lessongenerator = $this->getDataGenerator()->get_plugin_generator('mod_lesson');
-        $lessoninstance = $lessongenerator->create_instance(['course' => $course->id]);
-        $student = $generator->create_user();
-        $generator->enrol_user($student->id, $course->id, 'student');
-        $this->setUser($student);
-        $events = [
-            [
-                'name' => 'Start of assignment',
-                'description' => '',
-                'format' => 1,
-                'courseid' => $course->id,
-                'groupid' => 0,
-                'userid' => 2,
-                'modulename' => 'assign',
-                'instance' => $assigninstance->id,
-                'eventtype' => 'due',
-                'timestart' => time(),
-                'timeduration' => 86400,
-                'visible' => 1
-            ], [
-                'name' => 'Start of lesson',
-                'description' => '',
-                'format' => 1,
-                'courseid' => $course->id,
-                'groupid' => 0,
-                'userid' => 2,
-                'modulename' => 'lesson',
-                'instance' => $lessoninstance->id,
-                'eventtype' => 'end',
-                'timestart' => time(),
-                'timeduration' => 86400,
-                'visible' => 1
-            ]
-        ];
-        foreach ($events as $event) {
-            calendar_event::create($event, false);
-        }
-        $timestart = time() - 60;
-        $timeend = time() + 60;
-        // Get all events.
-        $events = \core_calendar\api::get_events($timestart, $timeend, true, 0, true);
-        $this->assertCount(2, $events);
-        // Disable the lesson module.
-        $modulerecord = $DB->get_record('modules', ['name' => 'lesson']);
-        $modulerecord->visible = 0;
-        $DB->update_record('modules', $modulerecord);
-        // Check that we only return the assign event.
-        $events = \core_calendar\api::get_events($timestart, $timeend, true, 0, true);
-        $this->assertCount(1, $events);
-        $event = reset($events);
-        $this->assertEquals('assign', $event->modulename);
-    }
-
-    /**
-     * Test for calendar_get_events() when there are user and group overrides.
-     */
-    public function test_calendar_get_events_with_overrides() {
-        global $DB;
-        $generator = $this->getDataGenerator();
-        $course = $generator->create_course();
-        $plugingenerator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
-        if (!isset($params['course'])) {
-            $params['course'] = $course->id;
-        }
-        $instance = $plugingenerator->create_instance($params);
-        // Create users.
-        $useroverridestudent = $generator->create_user();
-        $group1student = $generator->create_user();
-        $group2student = $generator->create_user();
-        $group12student = $generator->create_user();
-        $nogroupstudent = $generator->create_user();
-        // Enrol users.
-        $generator->enrol_user($useroverridestudent->id, $course->id, 'student');
-        $generator->enrol_user($group1student->id, $course->id, 'student');
-        $generator->enrol_user($group2student->id, $course->id, 'student');
-        $generator->enrol_user($group12student->id, $course->id, 'student');
-        $generator->enrol_user($nogroupstudent->id, $course->id, 'student');
-        // Create groups.
-        $group1 = $generator->create_group(['courseid' => $course->id]);
-        $group2 = $generator->create_group(['courseid' => $course->id]);
-        // Add members to groups.
-        $generator->create_group_member(['groupid' => $group1->id, 'userid' => $group1student->id]);
-        $generator->create_group_member(['groupid' => $group2->id, 'userid' => $group2student->id]);
-        $generator->create_group_member(['groupid' => $group1->id, 'userid' => $group12student->id]);
-        $generator->create_group_member(['groupid' => $group2->id, 'userid' => $group12student->id]);
-        $now = time();
-        // Events with the same module name, instance and event type.
-        $events = [
-            [
-                'name' => 'Assignment 1 due date',
-                'description' => '',
-                'format' => 0,
-                'courseid' => $course->id,
-                'groupid' => 0,
-                'userid' => 2,
-                'modulename' => 'assign',
-                'instance' => $instance->id,
-                'eventtype' => 'due',
-                'timestart' => $now,
-                'timeduration' => 0,
-                'visible' => 1
-            ], [
-                'name' => 'Assignment 1 due date - User override',
-                'description' => '',
-                'format' => 1,
-                'courseid' => 0,
-                'groupid' => 0,
-                'userid' => $useroverridestudent->id,
-                'modulename' => 'assign',
-                'instance' => $instance->id,
-                'eventtype' => 'due',
-                'timestart' => $now + 86400,
-                'timeduration' => 0,
-                'visible' => 1,
-                'priority' => CALENDAR_EVENT_USER_OVERRIDE_PRIORITY
-            ], [
-                'name' => 'Assignment 1 due date - Group A override',
-                'description' => '',
-                'format' => 1,
-                'courseid' => $course->id,
-                'groupid' => $group1->id,
-                'userid' => 2,
-                'modulename' => 'assign',
-                'instance' => $instance->id,
-                'eventtype' => 'due',
-                'timestart' => $now + (2 * 86400),
-                'timeduration' => 0,
-                'visible' => 1,
-                'priority' => 1,
-            ], [
-                'name' => 'Assignment 1 due date - Group B override',
-                'description' => '',
-                'format' => 1,
-                'courseid' => $course->id,
-                'groupid' => $group2->id,
-                'userid' => 2,
-                'modulename' => 'assign',
-                'instance' => $instance->id,
-                'eventtype' => 'due',
-                'timestart' => $now + (3 * 86400),
-                'timeduration' => 0,
-                'visible' => 1,
-                'priority' => 2,
-            ],
-        ];
-        foreach ($events as $event) {
-            calendar_event::create($event, false);
-        }
-        $timestart = $now - 100;
-        $timeend = $now + (3 * 86400);
-        $groups = [$group1->id, $group2->id];
-        // Get user override events.
-        $this->setUser($useroverridestudent);
-        $events = \core_calendar\api::get_events($timestart, $timeend, $useroverridestudent->id, $groups, $course->id);
-        $this->assertCount(1, $events);
-        $event = reset($events);
-        $this->assertEquals('Assignment 1 due date - User override', $event->name);
-        // Get event for user with override but with the timestart and timeend parameters only covering the original event.
-        $events = \core_calendar\api::get_events($timestart, $now, $useroverridestudent->id, $groups, $course->id);
-        $this->assertCount(0, $events);
-        // Get events for user that does not belong to any group and has no user override events.
-        $this->setUser($nogroupstudent);
-        $events = \core_calendar\api::get_events($timestart, $timeend, $nogroupstudent->id, $groups, $course->id);
-        $this->assertCount(1, $events);
-        $event = reset($events);
-        $this->assertEquals('Assignment 1 due date', $event->name);
-        // Get events for user that belongs to groups A and B and has no user override events.
-        $this->setUser($group12student);
-        $events = \core_calendar\api::get_events($timestart, $timeend, $group12student->id, $groups, $course->id);
-        $this->assertCount(1, $events);
-        $event = reset($events);
-        $this->assertEquals('Assignment 1 due date - Group B override', $event->name);
-        // Get events for user that belongs to group A and has no user override events.
-        $this->setUser($group1student);
-        $events = \core_calendar\api::get_events($timestart, $timeend, $group1student->id, $groups, $course->id);
-        $this->assertCount(1, $events);
-        $event = reset($events);
-        $this->assertEquals('Assignment 1 due date - Group A override', $event->name);
-        // Add repeating events.
-        $repeatingevents = [
-            [
-                'name' => 'Repeating site event',
-                'description' => '',
-                'format' => 1,
-                'courseid' => SITEID,
-                'groupid' => 0,
-                'userid' => 2,
-                'repeatid' => $event->id,
-                'modulename' => '0',
-                'instance' => 0,
-                'eventtype' => 'site',
-                'timestart' => $now + 86400,
-                'timeduration' => 0,
-                'visible' => 1,
-            ],
-            [
-                'name' => 'Repeating site event',
-                'description' => '',
-                'format' => 1,
-                'courseid' => SITEID,
-                'groupid' => 0,
-                'userid' => 2,
-                'repeatid' => $event->id,
-                'modulename' => '0',
-                'instance' => 0,
-                'eventtype' => 'site',
-                'timestart' => $now + (2 * 86400),
-                'timeduration' => 0,
-                'visible' => 1,
-            ],
-        ];
-        foreach ($repeatingevents as $event) {
-            calendar_event::create($event, false);
-        }
-        // Make sure repeating events are not filtered out.
-        $events = \core_calendar\api::get_events($timestart, $timeend, true, true, true);
-        $this->assertCount(3, $events);
-    }
-
-    /**
-     * Test the update_subscription() function.
-     */
-    public function test_update_subscription() {
-        $this->resetAfterTest(true);
-
-        $subscription = new stdClass();
-        $subscription->eventtype = 'site';
-        $subscription->name = 'test';
-        $id = \core_calendar\api::add_subscription($subscription);
-
-        $subscription = \core_calendar\api::get_subscription($id);
-        $subscription->name = 'awesome';
-        \core_calendar\api::update_subscription($subscription);
-        $sub = \core_calendar\api::get_subscription($id);
-        $this->assertEquals($subscription->name, $sub->name);
-
-        $subscription = \core_calendar\api::get_subscription($id);
-        $subscription->name = 'awesome2';
-        $subscription->pollinterval = 604800;
-        \core_calendar\api::update_subscription($subscription);
-        $sub = \core_calendar\api::get_subscription($id);
-        $this->assertEquals($subscription->name, $sub->name);
-        $this->assertEquals($subscription->pollinterval, $sub->pollinterval);
-
-        $subscription = new stdClass();
-        $subscription->name = 'awesome4';
-        $this->expectException('coding_exception');
-        \core_calendar\api::update_subscription($subscription);
-    }
-
-    public function test_add_subscription() {
-        global $DB, $CFG;
-
-        require_once($CFG->dirroot . '/lib/bennu/bennu.inc.php');
-
-        $this->resetAfterTest(true);
-
-        // Test for Microsoft Outlook 2010.
-        $subscription = new stdClass();
-        $subscription->name = 'Microsoft Outlook 2010';
-        $subscription->importfrom = CALENDAR_IMPORT_FROM_FILE;
-        $subscription->eventtype = 'site';
-        $id = \core_calendar\api::add_subscription($subscription);
-
-        $calendar = file_get_contents($CFG->dirroot . '/lib/tests/fixtures/ms_outlook_2010.ics');
-        $ical = new iCalendar();
-        $ical->unserialize($calendar);
-        $this->assertEquals($ical->parser_errors, array());
-
-        $sub = \core_calendar\api::get_subscription($id);
-        \core_calendar\api::import_icalendar_events($ical, $sub->courseid, $sub->id);
-        $count = $DB->count_records('event', array('subscriptionid' => $sub->id));
-        $this->assertEquals($count, 1);
-
-        // Test for OSX Yosemite.
-        $subscription = new stdClass();
-        $subscription->name = 'OSX Yosemite';
-        $subscription->importfrom = CALENDAR_IMPORT_FROM_FILE;
-        $subscription->eventtype = 'site';
-        $id = \core_calendar\api::add_subscription($subscription);
-
-        $calendar = file_get_contents($CFG->dirroot . '/lib/tests/fixtures/osx_yosemite.ics');
-        $ical = new iCalendar();
-        $ical->unserialize($calendar);
-        $this->assertEquals($ical->parser_errors, array());
-
-        $sub = \core_calendar\api::get_subscription($id);
-        \core_calendar\api::import_icalendar_events($ical, $sub->courseid, $sub->id);
-        $count = $DB->count_records('event', array('subscriptionid' => $sub->id));
-        $this->assertEquals($count, 1);
-
-        // Test for Google Gmail.
-        $subscription = new stdClass();
-        $subscription->name = 'Google Gmail';
-        $subscription->importfrom = CALENDAR_IMPORT_FROM_FILE;
-        $subscription->eventtype = 'site';
-        $id = \core_calendar\api::add_subscription($subscription);
-
-        $calendar = file_get_contents($CFG->dirroot . '/lib/tests/fixtures/google_gmail.ics');
-        $ical = new iCalendar();
-        $ical->unserialize($calendar);
-        $this->assertEquals($ical->parser_errors, array());
-
-        $sub = \core_calendar\api::get_subscription($id);
-        \core_calendar\api::import_icalendar_events($ical, $sub->courseid, $sub->id);
-        $count = $DB->count_records('event', array('subscriptionid' => $sub->id));
-        $this->assertEquals($count, 1);
-    }
-
     /**
      * 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
index f9fd7e5..5d9af03 100644 (file)
@@ -195,11 +195,11 @@ class core_calendar_type_testcase extends advanced_testcase {
             userdate($this->user->timecreated));
 
         // Test the calendar/lib.php functions.
-        $this->assertEquals($calendar->get_weekdays(), \core_calendar\api::get_days());
-        $this->assertEquals($calendar->get_starting_weekday(), \core_calendar\api::get_starting_weekday());
-        $this->assertEquals($calendar->get_num_days_in_month('1986', '9'), \core_calendar\api::get_days_in_month('9', '1986'));
-        $this->assertEquals($calendar->get_next_month('1986', '9'), \core_calendar\api::get_next_month('9', '1986'));
-        $this->assertEquals($calendar->get_prev_month('1986', '9'), \core_calendar\api::get_prev_month('9', '1986'));
+        $this->assertEquals($calendar->get_weekdays(), calendar_get_days());
+        $this->assertEquals($calendar->get_starting_weekday(), calendar_get_starting_weekday());
+        $this->assertEquals($calendar->get_num_days_in_month('1986', '9'), calendar_days_in_month('9', '1986'));
+        $this->assertEquals($calendar->get_next_month('1986', '9'), calendar_add_month('9', '1986'));
+        $this->assertEquals($calendar->get_prev_month('1986', '9'), calendar_sub_month('9', '1986'));
 
         // Test the lib/moodle.php functions.
         $this->assertEquals($calendar->get_num_days_in_month('1986', '9'), days_in_month('9', '1986'));
index 3331cbd..6f78848 100644 (file)
@@ -438,7 +438,7 @@ class core_calendar_events_testcase extends advanced_testcase {
 
         // Trigger and capture the event.
         $sink = $this->redirectEvents();
-        $id = \core_calendar\api::add_subscription($subscription);
+        $id = calendar_add_subscription($subscription);
 
         $events = $sink->get_events();
         $event = reset($events);
@@ -465,13 +465,13 @@ class core_calendar_events_testcase extends advanced_testcase {
         $subscription->eventtype = 'site';
         $subscription->name = 'test';
         $subscription->courseid = $this->course->id;
-        $subscription->id = \core_calendar\api::add_subscription($subscription);
+        $subscription->id = calendar_add_subscription($subscription);
         // Now edit it.
         $subscription->name = 'awesome';
 
         // Trigger and capture the event.
         $sink = $this->redirectEvents();
-        \core_calendar\api::update_subscription($subscription);
+        calendar_update_subscription($subscription);
         $events = $sink->get_events();
         $event = reset($events);
         // Check that the event data is valid.
@@ -497,11 +497,11 @@ class core_calendar_events_testcase extends advanced_testcase {
         $subscription->eventtype = 'site';
         $subscription->name = 'test';
         $subscription->courseid = $this->course->id;
-        $subscription->id = \core_calendar\api::add_subscription($subscription);
+        $subscription->id = calendar_add_subscription($subscription);
 
         // Trigger and capture the event.
         $sink = $this->redirectEvents();
-        \core_calendar\api::delete_subscription($subscription);
+        calendar_delete_subscription($subscription);
         $events = $sink->get_events();
         $event = reset($events);
         // Check that the event data is valid.
diff --git a/calendar/tests/lib_test.php b/calendar/tests/lib_test.php
new file mode 100644 (file)
index 0000000..797dc89
--- /dev/null
@@ -0,0 +1,395 @@
+<?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/>.
+
+/**
+ * Contains the class containing unit tests for the calendar lib.
+ *
+ * @package    core_calendar
+ * @copyright  2017 Mark Nelson <markn@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once(__DIR__ . '/helpers.php');
+
+/**
+ * Class contaning unit tests for the calendar lib.
+ *
+ * @package    core_calendar
+ * @copyright  2017 Mark Nelson <markn@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class core_calendar_lib_testcase extends advanced_testcase {
+
+    /**
+     * Tests set up
+     */
+    protected function setUp() {
+        $this->resetAfterTest();
+    }
+
+    /**
+     * Test that the get_events() function only returns activity events that are enabled.
+     */
+    public function test_get_events_with_disabled_module() {
+        global $DB;
+        $this->setAdminUser();
+        $generator = $this->getDataGenerator();
+        $course = $generator->create_course();
+        $assigngenerator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
+        $assigninstance = $assigngenerator->create_instance(['course' => $course->id]);
+        $lessongenerator = $this->getDataGenerator()->get_plugin_generator('mod_lesson');
+        $lessoninstance = $lessongenerator->create_instance(['course' => $course->id]);
+        $student = $generator->create_user();
+        $generator->enrol_user($student->id, $course->id, 'student');
+        $this->setUser($student);
+        $events = [
+            [
+                'name' => 'Start of assignment',
+                'description' => '',
+                'format' => 1,
+                'courseid' => $course->id,
+                'groupid' => 0,
+                'userid' => 2,
+                'modulename' => 'assign',
+                'instance' => $assigninstance->id,
+                'eventtype' => 'due',
+                'timestart' => time(),
+                'timeduration' => 86400,
+                'visible' => 1
+            ], [
+                'name' => 'Start of lesson',
+                'description' => '',
+                'format' => 1,
+                'courseid' => $course->id,
+                'groupid' => 0,
+                'userid' => 2,
+                'modulename' => 'lesson',
+                'instance' => $lessoninstance->id,
+                'eventtype' => 'end',
+                'timestart' => time(),
+                'timeduration' => 86400,
+                'visible' => 1
+            ]
+        ];
+        foreach ($events as $event) {
+            calendar_event::create($event, false);
+        }
+        $timestart = time() - 60;
+        $timeend = time() + 60;
+        // Get all events.
+        $events = calendar_get_events($timestart, $timeend, true, 0, true);
+        $this->assertCount(2, $events);
+        // Disable the lesson module.
+        $modulerecord = $DB->get_record('modules', ['name' => 'lesson']);
+        $modulerecord->visible = 0;
+        $DB->update_record('modules', $modulerecord);
+        // Check that we only return the assign event.
+        $events = calendar_get_events($timestart, $timeend, true, 0, true);
+        $this->assertCount(1, $events);
+        $event = reset($events);
+        $this->assertEquals('assign', $event->modulename);
+    }
+
+    /**
+     * Test for calendar_get_events() when there are user and group overrides.
+     */
+    public function test_calendar_get_events_with_overrides() {
+        global $DB;
+        $generator = $this->getDataGenerator();
+        $course = $generator->create_course();
+        $plugingenerator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
+        if (!isset($params['course'])) {
+            $params['course'] = $course->id;
+        }
+        $instance = $plugingenerator->create_instance($params);
+        // Create users.
+        $useroverridestudent = $generator->create_user();
+        $group1student = $generator->create_user();
+        $group2student = $generator->create_user();
+        $group12student = $generator->create_user();
+        $nogroupstudent = $generator->create_user();
+        // Enrol users.
+        $generator->enrol_user($useroverridestudent->id, $course->id, 'student');
+        $generator->enrol_user($group1student->id, $course->id, 'student');
+        $generator->enrol_user($group2student->id, $course->id, 'student');
+        $generator->enrol_user($group12student->id, $course->id, 'student');
+        $generator->enrol_user($nogroupstudent->id, $course->id, 'student');
+        // Create groups.
+        $group1 = $generator->create_group(['courseid' => $course->id]);
+        $group2 = $generator->create_group(['courseid' => $course->id]);
+        // Add members to groups.
+        $generator->create_group_member(['groupid' => $group1->id, 'userid' => $group1student->id]);
+        $generator->create_group_member(['groupid' => $group2->id, 'userid' => $group2student->id]);
+        $generator->create_group_member(['groupid' => $group1->id, 'userid' => $group12student->id]);
+        $generator->create_group_member(['groupid' => $group2->id, 'userid' => $group12student->id]);
+        $now = time();
+        // Events with the same module name, instance and event type.
+        $events = [
+            [
+                'name' => 'Assignment 1 due date',
+                'description' => '',
+                'format' => 0,
+                'courseid' => $course->id,
+                'groupid' => 0,
+                'userid' => 2,
+                'modulename' => 'assign',
+                'instance' => $instance->id,
+                'eventtype' => 'due',
+                'timestart' => $now,
+                'timeduration' => 0,
+                'visible' => 1
+            ], [
+                'name' => 'Assignment 1 due date - User override',
+                'description' => '',
+                'format' => 1,
+                'courseid' => 0,
+                'groupid' => 0,
+                'userid' => $useroverridestudent->id,
+                'modulename' => 'assign',
+                'instance' => $instance->id,
+                'eventtype' => 'due',
+                'timestart' => $now + 86400,
+                'timeduration' => 0,
+                'visible' => 1,
+                'priority' => CALENDAR_EVENT_USER_OVERRIDE_PRIORITY
+            ], [
+                'name' => 'Assignment 1 due date - Group A override',
+                'description' => '',
+                'format' => 1,
+                'courseid' => $course->id,
+                'groupid' => $group1->id,
+                'userid' => 2,
+                'modulename' => 'assign',
+                'instance' => $instance->id,
+                'eventtype' => 'due',
+                'timestart' => $now + (2 * 86400),
+                'timeduration' => 0,
+                'visible' => 1,
+                'priority' => 1,
+            ], [
+                'name' => 'Assignment 1 due date - Group B override',
+                'description' => '',
+                'format' => 1,
+                'courseid' => $course->id,
+                'groupid' => $group2->id,
+                'userid' => 2,
+                'modulename' => 'assign',
+                'instance' => $instance->id,
+                'eventtype' => 'due',
+                'timestart' => $now + (3 * 86400),
+                'timeduration' => 0,
+                'visible' => 1,
+                'priority' => 2,
+            ],
+        ];
+        foreach ($events as $event) {
+            calendar_event::create($event, false);
+        }
+        $timestart = $now - 100;
+        $timeend = $now + (3 * 86400);
+        $groups = [$group1->id, $group2->id];
+        // Get user override events.
+        $this->setUser($useroverridestudent);
+        $events = calendar_get_events($timestart, $timeend, $useroverridestudent->id, $groups, $course->id);
+        $this->assertCount(1, $events);
+        $event = reset($events);
+        $this->assertEquals('Assignment 1 due date - User override', $event->name);
+        // Get event for user with override but with the timestart and timeend parameters only covering the original event.
+        $events = calendar_get_events($timestart, $now, $useroverridestudent->id, $groups, $course->id);
+        $this->assertCount(0, $events);
+        // Get events for user that does not belong to any group and has no user override events.
+        $this->setUser($nogroupstudent);
+        $events = calendar_get_events($timestart, $timeend, $nogroupstudent->id, $groups, $course->id);
+        $this->assertCount(1, $events);
+        $event = reset($events);
+        $this->assertEquals('Assignment 1 due date', $event->name);
+        // Get events for user that belongs to groups A and B and has no user override events.
+        $this->setUser($group12student);
+        $events = calendar_get_events($timestart, $timeend, $group12student->id, $groups, $course->id);
+        $this->assertCount(1, $events);
+        $event = reset($events);
+        $this->assertEquals('Assignment 1 due date - Group B override', $event->name);
+        // Get events for user that belongs to group A and has no user override events.
+        $this->setUser($group1student);
+        $events = calendar_get_events($timestart, $timeend, $group1student->id, $groups, $course->id);
+        $this->assertCount(1, $events);
+        $event = reset($events);
+        $this->assertEquals('Assignment 1 due date - Group A override', $event->name);
+        // Add repeating events.
+        $repeatingevents = [
+            [
+                'name' => 'Repeating site event',
+                'description' => '',
+                'format' => 1,
+                'courseid' => SITEID,
+                'groupid' => 0,
+                'userid' => 2,
+                'repeatid' => $event->id,
+                'modulename' => '0',
+                'instance' => 0,
+                'eventtype' => 'site',
+                'timestart' => $now + 86400,
+                'timeduration' => 0,
+                'visible' => 1,
+            ],
+            [
+                'name' => 'Repeating site event',
+                'description' => '',
+                'format' => 1,
+                'courseid' => SITEID,
+                'groupid' => 0,
+                'userid' => 2,
+                'repeatid' => $event->id,
+                'modulename' => '0',
+                'instance' => 0,
+                'eventtype' => 'site',
+                'timestart' => $now + (2 * 86400),
+                'timeduration' => 0,
+                'visible' => 1,
+            ],
+        ];
+        foreach ($repeatingevents as $event) {
+            calendar_event::create($event, false);
+        }
+        // Make sure repeating events are not filtered out.
+        $events = calendar_get_events($timestart, $timeend, true, true, true);
+        $this->assertCount(3, $events);
+    }
+
+    public function test_get_course_cached() {
+        // Setup some test courses.
+        $course1 = $this->getDataGenerator()->create_course();
+        $course2 = $this->getDataGenerator()->create_course();
+        $course3 = $this->getDataGenerator()->create_course();
+
+        // Load courses into cache.
+        $coursecache = null;
+        calendar_get_course_cached($coursecache, $course1->id);
+        calendar_get_course_cached($coursecache, $course2->id);
+        calendar_get_course_cached($coursecache, $course3->id);
+
+        // Verify the cache.
+        $this->assertArrayHasKey($course1->id, $coursecache);
+        $cachedcourse1 = $coursecache[$course1->id];
+        $this->assertEquals($course1->id, $cachedcourse1->id);
+        $this->assertEquals($course1->shortname, $cachedcourse1->shortname);
+        $this->assertEquals($course1->fullname, $cachedcourse1->fullname);
+
+        $this->assertArrayHasKey($course2->id, $coursecache);
+        $cachedcourse2 = $coursecache[$course2->id];
+        $this->assertEquals($course2->id, $cachedcourse2->id);
+        $this->assertEquals($course2->shortname, $cachedcourse2->shortname);
+        $this->assertEquals($course2->fullname, $cachedcourse2->fullname);
+
+        $this->assertArrayHasKey($course3->id, $coursecache);
+        $cachedcourse3 = $coursecache[$course3->id];
+        $this->assertEquals($course3->id, $cachedcourse3->id);
+        $this->assertEquals($course3->shortname, $cachedcourse3->shortname);
+        $this->assertEquals($course3->fullname, $cachedcourse3->fullname);
+    }
+
+    /**
+     * Test the update_subscription() function.
+     */
+    public function test_update_subscription() {
+        $this->resetAfterTest(true);
+
+        $subscription = new stdClass();
+        $subscription->eventtype = 'site';
+        $subscription->name = 'test';
+        $id = calendar_add_subscription($subscription);
+
+        $subscription = calendar_get_subscription($id);
+        $subscription->name = 'awesome';
+        calendar_update_subscription($subscription);
+        $sub = calendar_get_subscription($id);
+        $this->assertEquals($subscription->name, $sub->name);
+
+        $subscription = calendar_get_subscription($id);
+        $subscription->name = 'awesome2';
+        $subscription->pollinterval = 604800;
+        calendar_update_subscription($subscription);
+        $sub = calendar_get_subscription($id);
+        $this->assertEquals($subscription->name, $sub->name);
+        $this->assertEquals($subscription->pollinterval, $sub->pollinterval);
+
+        $subscription = new stdClass();
+        $subscription->name = 'awesome4';
+        $this->expectException('coding_exception');
+        calendar_update_subscription($subscription);
+    }
+
+    public function test_add_subscription() {
+        global $DB, $CFG;
+
+        require_once($CFG->dirroot . '/lib/bennu/bennu.inc.php');
+
+        $this->resetAfterTest(true);
+
+        // Test for Microsoft Outlook 2010.
+        $subscription = new stdClass();
+        $subscription->name = 'Microsoft Outlook 2010';
+        $subscription->importfrom = CALENDAR_IMPORT_FROM_FILE;
+        $subscription->eventtype = 'site';
+        $id = calendar_add_subscription($subscription);
+
+        $calendar = file_get_contents($CFG->dirroot . '/lib/tests/fixtures/ms_outlook_2010.ics');
+        $ical = new iCalendar();
+        $ical->unserialize($calendar);
+        $this->assertEquals($ical->parser_errors, array());
+
+        $sub = calendar_get_subscription($id);
+        calendar_import_icalendar_events($ical, $sub->courseid, $sub->id);
+        $count = $DB->count_records('event', array('subscriptionid' => $sub->id));
+        $this->assertEquals($count, 1);
+
+        // Test for OSX Yosemite.
+        $subscription = new stdClass();
+        $subscription->name = 'OSX Yosemite';
+        $subscription->importfrom = CALENDAR_IMPORT_FROM_FILE;
+        $subscription->eventtype = 'site';
+        $id = calendar_add_subscription($subscription);
+
+        $calendar = file_get_contents($CFG->dirroot . '/lib/tests/fixtures/osx_yosemite.ics');
+        $ical = new iCalendar();
+        $ical->unserialize($calendar);
+        $this->assertEquals($ical->parser_errors, array());
+
+        $sub = calendar_get_subscription($id);
+        calendar_import_icalendar_events($ical, $sub->courseid, $sub->id);
+        $count = $DB->count_records('event', array('subscriptionid' => $sub->id));
+        $this->assertEquals($count, 1);
+
+        // Test for Google Gmail.
+        $subscription = new stdClass();
+        $subscription->name = 'Google Gmail';
+        $subscription->importfrom = CALENDAR_IMPORT_FROM_FILE;
+        $subscription->eventtype = 'site';
+        $id = calendar_add_subscription($subscription);
+
+        $calendar = file_get_contents($CFG->dirroot . '/lib/tests/fixtures/google_gmail.ics');
+        $ical = new iCalendar();
+        $ical->unserialize($calendar);
+        $this->assertEquals($ical->parser_errors, array());
+
+        $sub = calendar_get_subscription($id);
+        calendar_import_icalendar_events($ical, $sub->courseid, $sub->id);
+        $count = $DB->count_records('event', array('subscriptionid' => $sub->id));
+        $this->assertEquals($count, 1);
+    }
+}
\ No newline at end of file
index 8df030f..a55aee6 100644 (file)
@@ -91,7 +91,7 @@ if ($courseid != SITEID && !empty($courseid)) {
     navigation_node::override_active_url(new moodle_url('/course/view.php', array('id' => $course->id)));
 } else {
     $course = get_site();
-    $courses = \core_calendar\api::get_default_courses();
+    $courses = calendar_get_default_courses();
     $issite = true;
 }
 
@@ -158,7 +158,7 @@ switch($view) {
 echo $OUTPUT->container_start('bottom');
 if (!empty($CFG->enablecalendarexport)) {
     echo $OUTPUT->single_button(new moodle_url('export.php', array('course'=>$courseid)), get_string('exportcalendar', 'calendar'));
-    if (\core_calendar\api::can_add_event_to_course($course)) {
+    if (calendar_user_can_add_event($course)) {
         echo $OUTPUT->single_button(new moodle_url('/calendar/managesubscriptions.php', array('course'=>$courseid)), get_string('managesubscriptions', 'calendar'));
     }
     if (isloggedin()) {
index f387ad5..bf7f957 100644 (file)
@@ -62,7 +62,7 @@ class calendar_cron_task extends scheduled_task {
         foreach ($subscriptions as $sub) {
             mtrace("Updating calendar subscription {$sub->name} in course {$sub->courseid}");
             try {
-                $log = \core_calendar\api::update_subscription_events($sub->id);
+                $log = calendar_update_subscription_events($sub->id);
                 mtrace(trim(strip_tags($log)));
             } catch (\moodle_exception $ex) {
                 mtrace('Error updating calendar subscription: ' . $ex->getMessage());
index 0e86025..fa410b9 100644 (file)
@@ -53,7 +53,7 @@ class core_calendar_cron_task_testcase extends advanced_testcase {
         $subscription->url = $subscriptionurl;
         $subscription->pollinterval = 86400;
         $subscription->lastupdated = 0;
-        \core_calendar\api::add_subscription($subscription);
+        calendar_add_subscription($subscription);
 
         $this->expectOutputRegex('/Events imported: .* Events updated:/');
         $task = new \core\task\calendar_cron_task();
@@ -70,7 +70,7 @@ class core_calendar_cron_task_testcase extends advanced_testcase {
         $subscription->url = 'brokenurl';
         $subscription->pollinterval = 86400;
         $subscription->lastupdated = 0;
-        \core_calendar\api::add_subscription($subscription);
+        calendar_add_subscription($subscription);
 
         $this->expectOutputRegex('/Error updating calendar subscription: The given iCal URL is invalid/');
         $task = new \core\task\calendar_cron_task();
index 23b733d..ef810f4 100644 (file)
@@ -46,7 +46,7 @@ if (isset($CFG->calendar_maxevents)) {
 $calendarform = new core_user\form\calendar_form(null, array('userid' => $user->id));
 
 $user->timeformat = get_user_preferences('calendar_timeformat', '');
-$user->startwday  = \core_calendar\api::get_starting_weekday();
+$user->startwday  = calendar_get_starting_weekday();
 $user->maxevents  = get_user_preferences('calendar_maxevents', $defaultmaxevents);
 $user->lookahead  = get_user_preferences('calendar_lookahead', $defaultlookahead);
 $user->persistflt = get_user_preferences('calendar_persistflt', 0);