protected function sync_courseevents()

in classes/feature/calsync/task/syncoldevents.php [190:327]


    protected function sync_courseevents($courseid, $timecreated) {
        global $DB;
        $timestart = time();
        // Check the last time course events for this course were synced.
        // Using a direct query here so we don't run into static cache issues.
        $lastcoursesync = $DB->get_record('config_plugins', ['plugin' => 'local_o365', 'name' => 'cal_course_lastsync']);
        if (!empty($lastcoursesync)) {
            $lastcoursesync = unserialize($lastcoursesync->value);
            if (isset($lastcoursesync[$courseid]) && (int)$lastcoursesync[$courseid] > $timecreated) {
                // Course events for this course have been synced since this event was created, so we don't have to do it again.
                return true;
            }
        }

        $clientdata = \local_o365\oauth2\clientdata::instance_from_oidc();
        $httpclient = new \local_o365\httpclient();
        $calsync = new \local_o365\feature\calsync\main($clientdata, $httpclient);

        list($subscribersprimary, $subscribersnotprimary) = $this->get_subscribers('course', $courseid);

        $sql = 'SELECT ev.id AS eventid,
                       ev.name AS eventname,
                       ev.description AS eventdescription,
                       ev.timestart AS eventtimestart,
                       ev.timeduration AS eventtimeduration,
                       idmap.outlookeventid,
                       ev.userid AS eventuserid,
                       ev.groupid
                  FROM {event} ev
             LEFT JOIN {local_o365_calidmap} idmap ON ev.id = idmap.eventid AND idmap.userid = ev.userid
                 WHERE ev.courseid = ? ';
        $params = [$courseid];
        $events = $DB->get_recordset_sql($sql, $params);
        foreach ($events as $event) {
            try {
                mtrace('Syncing course event #'.$event->eventid);
                $grouplimit = null;
                // If this is a group event, get members and save for limiting later.
                if (!empty($event->groupid)) {
                    $sql = 'SELECT userid
                              FROM {groups_members}
                             WHERE groupid = ?';
                    $params = [$event->groupid];
                    $grouplimit = $DB->get_records_sql($sql, $params);
                }

                $subject = $event->eventname;
                $body = $event->eventdescription;
                $evstart = $event->eventtimestart;
                $evend = $evstart + $event->eventtimeduration;

                // Sync primary cal users first.
                if (!empty($subscribersprimary)) {
                    mtrace('Syncing primary calendar users.');
                    try {
                        // Determine attendees - if this is a group event, limit to group members.
                        if ($grouplimit !== null && is_array($grouplimit)) {
                            $eventattendees = array_intersect_key($subscribersprimary, $grouplimit);
                        } else {
                            $eventattendees = $subscribersprimary;
                        }

                        // If there's a stored outlookeventid the event exists in o365, so update it. Otherwise create it.
                        if (!empty($event->outlookeventid)) {
                            $calsync->update_event_raw($event->eventuserid, $event->outlookeventid,
                                ['attendees' => $eventattendees]);
                        } else {
                            $calid = null;
                            if (!empty($subscribersprimary[$event->eventuserid])) {
                                if (!empty($subscribersprimary[$event->eventuserid]->subo365calid)) {
                                    $calid = $subscribersprimary[$event->eventuserid]->subo365calid;
                                } else {
                                    $calid = null;
                                }
                            } else if (isset($subscribersnotprimary[$event->eventuserid])) {
                                if (!empty($subscribersnotprimary[$event->eventuserid]->subo365calid)) {
                                    $calid = $subscribersnotprimary[$event->eventuserid]->subo365calid;
                                } else {
                                    $calid = null;
                                }
                            }
                            $calsync->create_event_raw($event->eventuserid, $event->eventid, $subject, $body, $evstart, $evend,
                                    $eventattendees, [], $calid);
                        }
                    } catch (\Exception $e) {
                        mtrace('ERROR: '.$e->getMessage());
                    }
                }

                // Delete event for users who have an idmap record but are no longer subscribed.
                // Users would have an idmap record if they were non-primary calendar users, and are thus not taken care of with
                // the attendee update done above.
                $sql = 'SELECT userid, id, eventid, outlookeventid FROM {local_o365_calidmap} WHERE eventid = ? AND origin = ?';
                $idmapnosub = $DB->get_records_sql($sql, [$event->eventid, 'moodle']);
                $idmapnosub = array_diff_key($idmapnosub, $subscribersnotprimary, $subscribersprimary);
                if (isset($idmapnosub[$event->eventuserid])) {
                    // If the user who created the event is included, remove them. THIS IS VERY IMPORTANT. Otherwise any event
                    // in a calendar that the creator is not subscribed to will be removed, negating the work we did above with
                    // attendees.
                    unset($idmapnosub[$event->eventuserid]);
                }
                if (!empty($idmapnosub)) {
                    mtrace('Removing event for users who have unsubscribed.');
                    foreach ($idmapnosub as $userid => $usercalidmap) {
                        $calsync->delete_event_raw($userid, $usercalidmap->outlookeventid, $usercalidmap->id);
                    }
                }

                // Sync non-primary cal users.
                if (!empty($subscribersnotprimary)) {
                    mtrace('Syncing non-primary calendar users.');
                    foreach ($subscribersnotprimary as $userid => $user) {
                        // If we're syncing a group event, only sync users in the group.
                        if ($grouplimit !== null && is_array($grouplimit) && !isset($grouplimit[$user->id])) {
                            continue;
                        }
                        $calid = (!empty($user->subo365calid)) ? $user->subo365calid : null;
                        $calsync->ensure_event_synced_for_user($event->eventid, $user->id, $subject, $body, $evstart, $evend,
                            $calid);
                    }
                }
            } catch (\Exception $e) {
                // Could not sync this course event. Log and continue.
                mtrace('Error syncing course event #'.$event->eventid.': '.$e->getMessage());
            }
        }
        $events->close();

        if (!empty($lastcoursesync) && is_array($lastcoursesync)) {
            $lastcoursesync[$courseid] = $timestart;
        } else {
            $lastcoursesync = [$courseid => $timestart];
        }
        $lastcoursesync = serialize($lastcoursesync);
        set_config('cal_course_lastsync', $lastcoursesync, 'local_o365');

        return true;
    }