/** * Do the job. */ public function execute() { global $DB, $CFG; require_once $CFG->dirroot . '/calendar/lib.php'; // Get calendars set to sync in. $starttime = time(); \local_o365\feature\calsync\observers::set_event_import(true); // Using a direct query here so we don't run into static cache issues. $laststarttime = $DB->get_record('config_plugins', ['plugin' => 'local_o365', 'name' => 'calsyncinlastrun']); $laststarttime = !empty($laststarttime) && !empty($laststarttime->value) ? $laststarttime->value : 0; $httpclient = new \local_o365\httpclient(); $clientdata = \local_o365\oauth2\clientdata::instance_from_oidc(); $calsubs = $DB->get_recordset_select('local_o365_calsub', 'syncbehav = ? OR syncbehav = ?', ['in', 'both']); $calsync = new \local_o365\feature\calsync\main($clientdata, $httpclient); foreach ($calsubs as $i => $calsub) { try { $events = $calsync->get_events($calsub->user_id, $calsub->o365calid, $laststarttime); if (!empty($events) && is_array($events) && isset($events['value']) && is_array($events['value'])) { if (!empty($events['value'])) { foreach ($events['value'] as $i => $event) { if (!isset($event['Id'])) { mtrace('Skipped an event because of malformed data.'); continue; } $idmapexists = $DB->record_exists('local_o365_calidmap', ['outlookeventid' => $event['Id']]); if ($idmapexists === false) { // Create Moodle event. $eventparams = ['name' => $event['Subject'], 'description' => $event['Body']['Content'], 'eventtype' => $calsub->caltype, 'repeatid' => 0, 'modulename' => 0, 'instance' => 0, 'timestart' => strtotime($event['Start']), 'visible' => 1, 'uuid' => '', 'sequence' => 1]; $end = strtotime($event['End']); $eventparams['timeduration'] = $end - $eventparams['timestart']; if ($calsub->caltype === 'user') { $eventparams['userid'] = $calsub->caltypeid; } if ($calsub->caltype === 'course') { $eventparams['courseid'] = $calsub->caltypeid; } $moodleevent = \calendar_event::create($eventparams, false); if (!empty($moodleevent) && !empty($moodleevent->id)) { $idmaprec = ['eventid' => $moodleevent->id, 'outlookeventid' => $event['Id'], 'origin' => 'o365', 'userid' => $calsub->user_id]; $DB->insert_record('local_o365_calidmap', (object) $idmaprec); mtrace('Successfully imported event #' . $moodleevent->id); } } } } else { mtrace('No new events to sync in.'); } } else { mtrace('Bad response received when fetching events.'); } } catch (\Exception $e) { mtrace('Error: ' . $e->getMessage()); } } $calsubs->close(); \local_o365\feature\calsync\observers::set_event_import(false); set_config('calsyncinlastrun', $starttime, 'local_o365'); return true; }
/** * Handle a calendar_event_deleted event. * * @param \core\event\calendar_event_deleted $event The triggered event. * @return bool Success/Failure. */ public static function handle_calendar_event_deleted(\core\event\calendar_event_deleted $event) { $calsync = new \local_o365\feature\calsync\main(); return $calsync->delete_outlook_event($event->objectid); }
/** * Handle a calendar_event_deleted event. * * @param \core\event\calendar_event_deleted $event The triggered event. * @return bool Success/Failure. */ public static function handle_calendar_event_deleted(\core\event\calendar_event_deleted $event) { if (\local_o365\utils::is_configured() !== true) { return false; } $calsync = new \local_o365\feature\calsync\main(); return $calsync->delete_outlook_event($event->objectid); }
/** * Manage calendar syncing. */ public function mode_calendar() { global $DB, $USER, $OUTPUT, $PAGE; if (empty($this->o365connected)) { throw new \moodle_exception('ucp_notconnected', 'local_o365'); } $outlookresource = \local_o365\rest\calendar::get_resource(); if (empty($outlookresource)) { throw new \Exception('Not configured'); } $httpclient = new \local_o365\httpclient(); $clientdata = \local_o365\oauth2\clientdata::instance_from_oidc(); $token = \local_o365\oauth2\token::instance($USER->id, $outlookresource, $clientdata, $httpclient); $calsync = new \local_o365\feature\calsync\main(); $o365calendars = $calsync->get_calendars(); $customdata = ['o365calendars' => [], 'usercourses' => enrol_get_my_courses(['id', 'fullname']), 'cancreatesiteevents' => false, 'cancreatecourseevents' => []]; foreach ($o365calendars as $o365calendar) { $customdata['o365calendars'][] = ['id' => $o365calendar['Id'], 'name' => $o365calendar['Name']]; } $primarycalid = $customdata['o365calendars'][0]['id']; // Determine permissions to create events. Determines whether user can sync from o365 to Moodle. $customdata['cancreatesiteevents'] = has_capability('moodle/calendar:manageentries', \context_course::instance(SITEID)); foreach ($customdata['usercourses'] as $courseid => $course) { $cancreateincourse = has_capability('moodle/calendar:manageentries', \context_course::instance($courseid)); $customdata['cancreatecourseevents'][$courseid] = $cancreateincourse; } $mform = new \local_o365\feature\calsync\form\subscriptions('?action=calendar', $customdata); if ($mform->is_cancelled()) { redirect(new \moodle_url('/local/o365/ucp.php')); } else { if ($fromform = $mform->get_data()) { \local_o365\feature\calsync\form\subscriptions::update_subscriptions($fromform, $primarycalid, $customdata['cancreatesiteevents'], $customdata['cancreatecourseevents']); redirect(new \moodle_url('/local/o365/ucp.php')); } else { $PAGE->requires->jquery(); $defaultdata = []; $existingsubsrs = $DB->get_recordset('local_o365_calsub', ['user_id' => $USER->id]); foreach ($existingsubsrs as $existingsubrec) { if ($existingsubrec->caltype === 'site') { $defaultdata['sitecal']['checked'] = '1'; $defaultdata['sitecal']['syncwith'] = $existingsubrec->o365calid; $defaultdata['sitecal']['syncbehav'] = $existingsubrec->syncbehav; } else { if ($existingsubrec->caltype === 'user') { $defaultdata['usercal']['checked'] = '1'; $defaultdata['usercal']['syncwith'] = $existingsubrec->o365calid; $defaultdata['usercal']['syncbehav'] = $existingsubrec->syncbehav; } else { if ($existingsubrec->caltype === 'course') { $defaultdata['coursecal'][$existingsubrec->caltypeid]['checked'] = '1'; $defaultdata['coursecal'][$existingsubrec->caltypeid]['syncwith'] = $existingsubrec->o365calid; $defaultdata['coursecal'][$existingsubrec->caltypeid]['syncbehav'] = $existingsubrec->syncbehav; } } } } $existingsubsrs->close(); $mform->set_data($defaultdata); echo $OUTPUT->header(); $mform->display(); echo $OUTPUT->footer(); } } }
/** * Sync all user events for a given user with Outlook. * * @param int $userid The ID of the user to sync. * @param int $timecreated The time the task was created. */ protected function sync_userevents($userid, $timecreated) { global $DB; $timestart = time(); // Check the last time user events for this user were synced. // Using a direct query here so we don't run into static cache issues. $lastusersync = $DB->get_record('config_plugins', ['plugin' => 'local_o365', 'name' => 'cal_user_lastsync']); if (!empty($lastusersync)) { $lastusersync = unserialize($lastusersync->value); if (is_array($lastusersync) && isset($lastusersync[$userid]) && (int) $lastusersync[$userid] > $timecreated) { // User events for this user 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); $usertoken = $calsync->get_user_token($userid); if (empty($usertoken)) { // No token, can't sync. \local_o365\utils::debug('Could not get user token for calendar sync.'); return false; } $subscription = $DB->get_record('local_o365_calsub', ['user_id' => $userid, 'caltype' => 'user']); $sql = 'SELECT ev.id AS eventid, ev.name AS eventname, ev.description AS eventdescription, ev.timestart AS eventtimestart, ev.timeduration AS eventtimeduration, idmap.outlookeventid, idmap.origin AS idmaporigin FROM {event} ev LEFT JOIN {local_o365_calidmap} idmap ON ev.id = idmap.eventid AND idmap.userid = ev.userid WHERE ev.courseid = 0 AND ev.groupid = 0 AND ev.userid = ?'; $events = $DB->get_recordset_sql($sql, [$userid]); foreach ($events as $event) { mtrace('Syncing user event #' . $event->eventid); if (!empty($subscription)) { if (empty($event->outlookeventid)) { // Event not synced, if outward subscription exists sync to o365. if ($subscription->syncbehav === 'out' || $subscription->syncbehav === 'both') { mtrace('Creating event in Outlook.'); $subject = $event->eventname; $body = $event->eventdescription; $evstart = $event->eventtimestart; $evend = $event->eventtimestart + $event->eventtimeduration; $calid = !empty($subscription->o365calid) ? $subscription->o365calid : null; if (isset($subscription->isprimary) && $subscription->isprimary == 1) { $calid = null; } $calsync->create_event_raw($userid, $event->eventid, $subject, $body, $evstart, $evend, [], [], $calid); } else { mtrace('Not creating event in Outlook. (Sync settings are inward-only.)'); } } else { // Event synced. If event was created in Moodle and subscription is inward-only, delete o365 event. if ($event->idmaporigin === 'moodle' && $subscription->syncbehav === 'in') { mtrace('Removing event from Outlook (Created in Moodle, sync settings are inward-only.)'); $calsync->delete_event_raw($userid, $event->outlookeventid); } else { mtrace('Event already synced.'); } } } else { // No subscription exists. Delete relevant events. if (!empty($event->outlookeventid)) { if ($event->idmaporigin === 'moodle') { mtrace('Removing event from Outlook.'); // Event was created in Moodle, delete o365 event. $calsync->delete_event_raw($userid, $event->outlookeventid); } else { mtrace('Not removing event from Outlook (It was created there.)'); } } else { mtrace('Did not have an outlookeventid. Event not synced?'); } } } $events->close(); if (!empty($lastusersync) && is_array($lastusersync)) { $lastusersync[$userid] = $timestart; } else { $lastusersync = [$userid => $timestart]; } $lastusersync = serialize($lastusersync); set_config('cal_user_lastsync', $lastusersync, 'local_o365'); return true; }