/** * Do the job. */ public function execute() { global $DB; $oidcconfig = get_config('auth_oidc'); if (empty($oidcconfig)) { throw new \moodle_exception('erroracpauthoidcnotconfig', 'local_o365'); } $spresource = \local_o365\rest\sharepoint::get_resource(); if (empty($spresource)) { throw new \moodle_exception('erroracplocalo365notconfig', 'local_o365'); } $httpclient = new \local_o365\httpclient(); $clientdata = new \local_o365\oauth2\clientdata($oidcconfig->clientid, $oidcconfig->clientsecret, $oidcconfig->authendpoint, $oidcconfig->tokenendpoint); $sptoken = \local_o365\oauth2\systemtoken::instance(null, $spresource, $clientdata, $httpclient); if (empty($sptoken)) { throw new \moodle_exception('erroracpnosptoken', 'local_o365'); } $sharepoint = new \local_o365\rest\sharepoint($sptoken, $httpclient); $sharepoint->set_site(''); $moodlesiteuri = $sharepoint->get_moodle_parent_site_uri(); if ($sharepoint->site_exists($moodlesiteuri) === false) { $moodlesitename = get_string('acp_parentsite_name', 'local_o365'); $moodlesitedesc = get_string('acp_parentsite_desc', 'local_o365'); $frontpagerec = $DB->get_record('course', ['id' => SITEID], 'id,shortname'); if (!empty($frontpagerec) && !empty($frontpagerec->shortname)) { $moodlesitename = $frontpagerec->shortname; } $result = $sharepoint->create_site($moodlesitename, $moodlesiteuri, $moodlesitedesc); mtrace('Created parent site'); } $courses = $DB->get_recordset('course'); $successes = []; $failures = []; foreach ($courses as $course) { if ($course->id == SITEID) { continue; } try { $sharepoint->create_course_site($course); $successes[] = $course->id; mtrace('Created course subsite for course ' . $course->id); } catch (\Exception $e) { $failures[$course->id] = $e->getMessage(); } } set_config('sharepoint_initialized', '1', 'local_o365'); }
/** * Sync Sharepoint course site access when a role was assigned or unassigned for a user. * * @param int $roleid The ID of the role that was assigned/unassigned. * @param int $userid The ID of the user that it was assigned to or unassigned from. * @param int $contextid The ID of the context the role was assigned/unassigned in. * @return bool Success/Failure. */ public static function sync_spsite_access_for_roleassign_change($roleid, $userid, $contextid) { global $DB; $requiredcap = \local_o365\rest\sharepoint::get_course_site_required_capability(); // Check if the role affected the required capability. $rolecapsql = "SELECT *\n FROM {role_capabilities}\n WHERE roleid = ? AND capability = ?"; $capassignrec = $DB->get_record_sql($rolecapsql, [$roleid, $requiredcap]); if (empty($capassignrec) || $capassignrec->permission == CAP_INHERIT) { // Role doesn't affect required capability. Doesn't concern us. return false; } $context = \context::instance_by_id($contextid, IGNORE_MISSING); if (empty($context)) { // Invalid context, stop here. return false; } if ($context->contextlevel == CONTEXT_COURSE) { $courseid = $context->instanceid; $user = $DB->get_record('user', ['id' => $userid]); if (empty($user)) { // Bad userid. return false; } $userupn = \local_o365\rest\azuread::get_muser_upn($user); if (empty($userupn)) { // No user UPN, can't continue. return false; } $spgroupsql = 'SELECT * FROM {local_o365_coursespsite} site JOIN {local_o365_spgroupdata} grp ON grp.coursespsiteid = site.id WHERE site.courseid = ? AND grp.permtype = ?'; $spgrouprec = $DB->get_record_sql($spgroupsql, [$courseid, 'contribute']); if (empty($spgrouprec)) { // No sharepoint group, can't fix that here. return false; } // If the context is a course context we can change SP access now. $sharepoint = static::construct_sharepoint_api_with_system_user(); if (empty($sharepoint)) { // O365 not configured. return false; } $hascap = has_capability($requiredcap, $context, $user); if ($hascap === true) { // Add to group. $sharepoint->add_user_to_group($userupn, $spgrouprec->groupid, $user->id); } else { // Remove from group. $sharepoint->remove_user_from_group($userupn, $spgrouprec->groupid, $user->id); } return true; } else { if ($context->get_course_context(false) == false) { // If the context is higher than a course, we have to run a sync in cron. $spaccesssync = new \local_o365\task\sharepointaccesssync(); $spaccesssync->set_custom_data(['roleid' => $roleid, 'userid' => $userid, 'contextid' => $contextid]); \core\task\manager::queue_adhoc_task($spaccesssync); return true; } } }
/** * Get listing for a course folder. * * @param string $path Folder path. * @return array List of $list array and $path array. */ protected function get_listing_course($path = '') { global $USER, $OUTPUT; $list = []; $breadcrumb = [['name' => $this->name, 'path' => '/'], ['name' => 'Courses', 'path' => '/courses/']]; $reqcap = \local_o365\rest\sharepoint::get_course_site_required_capability(); $courses = get_user_capability_course($reqcap, $USER->id, true, 'shortname'); // Reindex courses array using course id. $coursesbyid = []; foreach ($courses as $i => $course) { $coursesbyid[$course->id] = $course; unset($courses[$i]); } unset($courses); if ($path === '/') { // Show available courses. foreach ($coursesbyid as $course) { $list[] = ['title' => $course->shortname, 'path' => '/courses/' . $course->id, 'thumbnail' => $OUTPUT->pix_url(file_folder_icon(90))->out(false), 'children' => []]; } } else { $pathtrimmed = trim($path, '/'); $pathparts = explode('/', $pathtrimmed); if (!is_numeric($pathparts[0])) { throw new \moodle_exception('errorbadpath', 'repository_office365'); } $courseid = (int) $pathparts[0]; unset($pathparts[0]); $relpath = !empty($pathparts) ? implode('/', $pathparts) : ''; if (isset($coursesbyid[$courseid])) { if ($this->path_is_upload($path) === false) { $sharepointclient = $this->get_sharepoint_apiclient(); if (!empty($sharepointclient)) { $parentsiteuri = $sharepointclient->get_course_subsite_uri($coursesbyid[$courseid]->id); $sharepointclient->set_site($parentsiteuri); try { $fullpath = !empty($relpath) ? '/' . $relpath : '/'; $contents = $sharepointclient->get_files($fullpath); $list = $this->contents_api_response_to_list($contents, $path, 'sharepoint', $parentsiteuri); } catch (\Exception $e) { $list = []; } } } $curpath = '/courses/' . $courseid; $breadcrumb[] = ['name' => $coursesbyid[$courseid]->shortname, 'path' => $curpath]; foreach ($pathparts as $pathpart) { if (!empty($pathpart)) { $curpath .= '/' . $pathpart; $breadcrumb[] = ['name' => $pathpart, 'path' => $curpath]; } } } } return [$list, $breadcrumb]; }
/** * Check if a given URL is a valid SharePoint site. */ public function mode_checksharepointsite() { $data = new \stdClass(); $success = false; $uncleanurl = required_param('site', PARAM_TEXT); $clientdata = \local_o365\oauth2\clientdata::instance_from_oidc(); $httpclient = new \local_o365\httpclient(); $data->result = \local_o365\rest\sharepoint::validate_site($uncleanurl, $clientdata, $httpclient); $success = true; echo $this->ajax_response($data, $success); }
/** * Looks for links pointing to Office 365 Video content and processes them. * * @param $link HTML tag containing a link * @return string HTML content after processing. */ function filter_oembed_o365videocallback($link) { if (empty($link[3])) { return $link[0]; } $link[3] = preg_replace("/&/", "&", $link[3]); $values = array(); parse_str($link[3], $values); if (empty($values['chid']) || empty($values['vid'])) { return $link[0]; } if (!\local_o365\rest\sharepoint::is_configured()) { \local_o365\utils::debug('filter_oembed share point is not configured', 'filter_oembed_o365videocallback'); return $link[0]; } try { $spresource = \local_o365\rest\sharepoint::get_resource(); if (!empty($spresource)) { $httpclient = new \local_o365\httpclient(); $clientdata = \local_o365\oauth2\clientdata::instance_from_oidc(); $sptoken = \local_o365\oauth2\systemtoken::instance(null, $spresource, $clientdata, $httpclient); if (!empty($sptoken)) { $sharepoint = new \local_o365\rest\sharepoint($sptoken, $httpclient); // Retrieve api url for video service. $url = $sharepoint->videoservice_discover(); if (!empty($url)) { $sharepoint->override_resource($url); $width = 640; if (!empty($values['width'])) { $width = $values['width']; } $height = 360; if (!empty($values['height'])) { $height = $values['height']; } // Retrieve embed code. return $sharepoint->get_video_embed_code($values['chid'], $values['vid'], $width, $height); } } } } catch (\Exception $e) { \local_o365\utils::debug('filter_oembed share point execption: ' . $e->getMessage(), 'filter_oembed_o365videocallback'); } return $link[0]; }
/** * Test create_course_site method. */ public function test_create_course_site() { global $DB; $requiredcapability = \local_o365\rest\sharepoint::get_course_site_required_capability(); $course = $this->getDataGenerator()->create_course(); $role = $this->getDataGenerator()->create_role(['archetype' => 'editingteacher']); $coursecontext = \context_course::instance($course->id); $user1 = $this->getDataGenerator()->create_user(['auth' => 'oidc']); $user2 = $this->getDataGenerator()->create_user(['auth' => 'oidc']); $aaduserdata = (object) ['type' => 'user', 'subtype' => '', 'objectid' => '', 'moodleid' => $user1->id, 'o365name' => '*****@*****.**', 'timecreated' => time(), 'timemodified' => time()]; $aaduserdata->id = $DB->insert_record('local_o365_objects', $aaduserdata); $result = $this->getDataGenerator()->role_assign($role, $user1->id, $coursecontext); $httpclient = new \local_o365\tests\mockhttpclient(); $httpresponses = ['', $this->get_response_create_site($course->fullname, $course->shortname, $course->summary), $this->get_response_create_group('testgroup', 'testgroup'), $this->get_response_assign_group_permission(), $this->get_response_add_user_to_group($aaduserdata->userupn)]; $httpclient->set_responses($httpresponses); $apiclient = new \local_o365\rest\sharepoint($this->get_mock_token(), $httpclient); $apiclient->create_course_site($course->id); $coursespsite = $DB->get_record('local_o365_coursespsite', ['courseid' => $course->id]); $this->assertNotEmpty($coursespsite); $this->assertEquals('/moodle/' . $course->shortname, $coursespsite->siteurl); $spgroupdata = $DB->get_records('local_o365_spgroupdata', ['coursespsiteid' => $coursespsite->id]); $this->assertNotEmpty($spgroupdata); }
/** * Do the job. */ public function execute() { global $DB; // API Setup. try { $spresource = \local_o365\rest\sharepoint::get_resource(); if (empty($spresource)) { throw new \moodle_exception('erroracplocalo365notconfig', 'local_o365'); } $httpclient = new \local_o365\httpclient(); $clientdata = \local_o365\oauth2\clientdata::instance_from_oidc(); $sptoken = \local_o365\oauth2\systemtoken::instance(null, $spresource, $clientdata, $httpclient); if (empty($sptoken)) { throw new \moodle_exception('erroracpnosptoken', 'local_o365'); } $sharepoint = new \local_o365\rest\sharepoint($sptoken, $httpclient); } catch (\Exception $e) { $errmsg = 'ERROR: Problem initializing SharePoint API. Reason: ' . $e->getMessage(); mtrace($errmsg); \local_o365\utils::debug($errmsg, 'local_o365\\task\\sharepointinit::execute'); set_config('sharepoint_initialized', 'error', 'local_o365'); return false; } // Create parent site(s). try { mtrace('Creating parent site for Moodle...'); $moodlesiteuri = $sharepoint->get_moodle_parent_site_uri(); $sitelevels = explode('/', $moodlesiteuri); $currentparentsite = ''; foreach ($sitelevels as $partialurl) { $sharepoint->set_site($currentparentsite); if ($sharepoint->site_exists($currentparentsite . '/' . $partialurl) === false) { $moodlesitename = get_string('acp_parentsite_name', 'local_o365'); $moodlesitedesc = get_string('acp_parentsite_desc', 'local_o365'); $frontpagerec = $DB->get_record('course', ['id' => SITEID], 'id,shortname'); if (!empty($frontpagerec) && !empty($frontpagerec->shortname)) { $moodlesitename = $frontpagerec->shortname; } mtrace('Setting parent site to "' . $currentparentsite . '", creating subsite "' . $partialurl . '"'); $result = $sharepoint->create_site($moodlesitename, $partialurl, $moodlesitedesc); $currentparentsite .= '/' . $partialurl; mtrace('Created parent site "' . $currentparentsite . '"'); } else { $currentparentsite .= '/' . $partialurl; mtrace('Parent site "' . $currentparentsite . '" already exists.'); } } mtrace('Finished creating Moodle parent site.'); } catch (\Exception $e) { $errmsg = 'ERROR: Problem creating parent site. Reason: ' . $e->getMessage(); mtrace($errmsg); \local_o365\utils::debug($errmsg, 'local_o365\\task\\sharepointinit::execute'); set_config('sharepoint_initialized', 'error', 'local_o365'); return false; } // Create course sites. mtrace('Creating course subsites in "' . $moodlesiteuri . '"'); $sharepoint->set_site($moodlesiteuri); $courses = $DB->get_recordset('course'); $successes = []; $failures = []; foreach ($courses as $course) { if ($course->id == SITEID) { continue; } try { $sharepoint->create_course_site($course); $successes[] = $course->id; mtrace('Created course subsite for course ' . $course->id); } catch (\Exception $e) { mtrace('Encountered error creating course subsite for course ' . $course->id); $failures[$course->id] = $e->getMessage(); } } if (!empty($failures)) { $errmsg = 'ERROR: Encountered problems creating course sites.'; mtrace($errmsg . ' See logs.'); \local_o365\utils::debug($errmsg, 'local_o365\\task\\sharepointinit::execute', $failures); set_config('sharepoint_initialized', 'error', 'local_o365'); } else { set_config('sharepoint_initialized', '1', 'local_o365'); mtrace('SharePoint successfully initialized.'); return true; } }
/** * Create a course subsite. * * @param \stdClass $course A course record to create the subsite from. * @return \stdClass An association record. */ public function create_course_subsite($course) { return parent::create_course_subsite($course); }
/** * Do the job. */ public function execute() { $reqcap = \local_o365\rest\sharepoint::get_course_site_required_capability(); $oidcconfig = get_config('auth_oidc'); if (!empty($oidcconfig)) { $spresource = \local_o365\rest\sharepoint::get_resource(); if (!empty($spresource)) { $httpclient = new \local_o365\httpclient(); $clientdata = new \local_o365\oauth2\clientdata($oidcconfig->clientid, $oidcconfig->clientsecret, $oidcconfig->authendpoint, $oidcconfig->tokenendpoint); $sptoken = \local_o365\oauth2\systemtoken::instance(null, $spresource, $clientdata, $httpclient); if (!empty($sptoken)) { $sharepoint = new \local_o365\rest\sharepoint($sptoken, $httpclient); } } } if (empty($sharepoint)) { throw new \moodle_exception('errorcreatingsharepointclient', 'local_o365'); } $opdata = $this->get_custom_data(); if ($opdata->userid !== '*' && $opdata->roleid !== '*' && !empty($opdata->contextid)) { // Single user role assign/unassign. $this->do_role_assignmentchange($opdata->roleid, $opdata->userid, $opdata->contextid, $reqcap, $sharepoint); } else { if ($opdata->userid === '*' && $opdata->roleid !== '*') { // Capability update. $this->do_role_capabilitychange($opdata->roleid, $reqcap, $sharepoint); } else { if ($opdata->roleid === '*' && $opdata->userid === '*') { // Role deleted. $this->do_role_delete($reqcap, $sharepoint); } } } }
/** * Get content for a connected user. * * @return string Block content. */ protected function get_content_connected() { global $PAGE, $DB; $o365config = get_config('local_o365'); $html = ''; $langconnected = get_string('o365connected', 'block_microsoft'); $html .= '<h5>' . $langconnected . '</h5>'; $outlookurl = new \moodle_url('/local/o365/ucp.php?action=calendar'); $outlookstr = get_string('linkoutlook', 'block_microsoft'); $sharepointstr = get_string('linksharepoint', 'block_microsoft'); $prefsurl = new \moodle_url('/local/o365/ucp.php'); $prefsstr = get_string('linkprefs', 'block_microsoft'); $connecturl = new \moodle_url('/local/o365/ucp.php', ['action' => 'aadlogin']); $connectstr = get_string('linkconnection', 'block_microsoft'); $items = []; if ($PAGE->context instanceof \context_course && $PAGE->context->instanceid !== SITEID) { if (!empty($o365config->sharepointlink)) { $coursespsite = $DB->get_record('local_o365_coursespsite', ['courseid' => $PAGE->context->instanceid]); if (!empty($coursespsite)) { $spsite = \local_o365\rest\sharepoint::get_resource(); if (!empty($spsite)) { $spurl = $spsite . '/' . $coursespsite->siteurl; $spattrs = ['class' => 'servicelink block_microsoft_sharepoint', 'target' => '_blank']; $items[] = html_writer::link($spurl, $sharepointstr, $spattrs); $items[] = '<hr/>'; } } } } $items[] = $this->render_onenote(); $items[] = \html_writer::link($outlookurl, $outlookstr, ['class' => 'servicelink block_microsoft_outlook']); $items[] = \html_writer::link($prefsurl, $prefsstr, ['class' => 'servicelink block_microsoft_preferences']); $items[] = \html_writer::link($connecturl, $connectstr, ['class' => 'servicelink block_microsoft_connection']); $html .= \html_writer::alist($items); return $html; }
/** * Get content for a connected user. * * @return string Block content. */ protected function get_content_connected() { global $PAGE, $DB, $CFG, $SESSION, $USER, $OUTPUT; $o365config = get_config('local_o365'); $html = ''; $aadsync = get_config('local_o365', 'aadsync'); $aadsync = array_flip(explode(',', $aadsync)); // Only profile sync once for each session. if (empty($SESSION->block_microsoft_profilesync) && isset($aadsync['photosynconlogin'])) { $PAGE->requires->jquery(); $PAGE->requires->js('/blocks/microsoft/js/microsoft.js'); $PAGE->requires->js_init_call('microsoft_update_profile', array($CFG->wwwroot)); } $user = $DB->get_record('user', array('id' => $USER->id)); $langconnected = get_string('o365connected', 'block_microsoft', $user); $html .= '<h5>' . $langconnected . '</h5>'; if (!empty($user->picture)) { $html .= '<div class="profilepicture">'; $html .= $OUTPUT->user_picture($user, array('size' => 100, 'class' => 'block_microsoft_profile')); $html .= '</div>'; } $outlookurl = new \moodle_url('/local/o365/ucp.php?action=calendar'); $outlookstr = get_string('linkoutlook', 'block_microsoft'); $sharepointstr = get_string('linksharepoint', 'block_microsoft'); $prefsurl = new \moodle_url('/local/o365/ucp.php'); $prefsstr = get_string('linkprefs', 'block_microsoft'); $connecturl = new \moodle_url('/local/o365/ucp.php', ['action' => 'aadlogin']); $connectstr = get_string('linkconnection', 'block_microsoft'); $items = []; if ($PAGE->context instanceof \context_course && $PAGE->context->instanceid !== SITEID) { if (!empty($o365config->sharepointlink)) { $coursespsite = $DB->get_record('local_o365_coursespsite', ['courseid' => $PAGE->context->instanceid]); if (!empty($coursespsite)) { $spsite = \local_o365\rest\sharepoint::get_resource(); if (!empty($spsite)) { $spurl = $spsite . '/' . $coursespsite->siteurl; $spattrs = ['class' => 'servicelink block_microsoft_sharepoint', 'target' => '_blank']; $items[] = html_writer::link($spurl, $sharepointstr, $spattrs); $items[] = '<hr/>'; } } } } $items[] = $this->render_onenote(); $items[] = \html_writer::link($outlookurl, $outlookstr, ['class' => 'servicelink block_microsoft_outlook']); $items[] = \html_writer::link($prefsurl, $prefsstr, ['class' => 'servicelink block_microsoft_preferences']); $items[] = \html_writer::link($connecturl, $connectstr, ['class' => 'servicelink block_microsoft_connection']); $downloadlinks = $this->get_content_o365download(); foreach ($downloadlinks as $link) { $items[] = $link; } $html .= \html_writer::alist($items); return $html; }