forked from EVOgeek/Vmeda.Online
230 lines
7.6 KiB
TypeScript
230 lines
7.6 KiB
TypeScript
// (C) Copyright 2015 Martin Dougiamas
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
import { Injectable } from '@angular/core';
|
|
import { TranslateService } from '@ngx-translate/core';
|
|
import { CoreAppProvider } from '@providers/app';
|
|
import { CoreFileProvider } from '@providers/file';
|
|
import { CoreSitesProvider } from '@providers/sites';
|
|
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
|
import { CoreUtilsProvider } from '@providers/utils/utils';
|
|
import { CoreUrlUtilsProvider } from '@providers/utils/url';
|
|
import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper';
|
|
import { CoreSite } from '@classes/site';
|
|
|
|
export interface AddonModLtiParam {
|
|
name: string;
|
|
value: string;
|
|
}
|
|
|
|
/**
|
|
* Service that provides some features for LTI.
|
|
*/
|
|
@Injectable()
|
|
export class AddonModLtiProvider {
|
|
static COMPONENT = 'mmaModLti';
|
|
|
|
protected ROOT_CACHE_KEY = 'mmaModLti:';
|
|
protected LAUNCHER_FILE_NAME = 'lti_launcher.html';
|
|
|
|
constructor(private fileProvider: CoreFileProvider,
|
|
private sitesProvider: CoreSitesProvider,
|
|
private textUtils: CoreTextUtilsProvider,
|
|
private urlUtils: CoreUrlUtilsProvider,
|
|
private utils: CoreUtilsProvider,
|
|
private translate: TranslateService,
|
|
private appProvider: CoreAppProvider,
|
|
private logHelper: CoreCourseLogHelperProvider) {}
|
|
|
|
/**
|
|
* Delete launcher.
|
|
*
|
|
* @return {Promise<any>} Promise resolved when the launcher file is deleted.
|
|
*/
|
|
deleteLauncher(): Promise<any> {
|
|
return this.fileProvider.removeFile(this.LAUNCHER_FILE_NAME);
|
|
}
|
|
|
|
/**
|
|
* Generates a launcher file.
|
|
*
|
|
* @param {string} url Launch URL.
|
|
* @param {AddonModLtiParam[]} params Launch params.
|
|
* @return {Promise<string>} Promise resolved with the file URL.
|
|
*/
|
|
generateLauncher(url: string, params: AddonModLtiParam[]): Promise<string> {
|
|
if (!this.fileProvider.isAvailable()) {
|
|
return Promise.resolve(url);
|
|
}
|
|
|
|
// Generate a form with the params.
|
|
let text = '<form action="' + url + '" name="ltiLaunchForm" ' +
|
|
'method="post" encType="application/x-www-form-urlencoded">\n';
|
|
params.forEach((p) => {
|
|
if (p.name == 'ext_submit') {
|
|
text += ' <input type="submit"';
|
|
} else {
|
|
text += ' <input type="hidden" name="' + this.textUtils.escapeHTML(p.name) + '"';
|
|
}
|
|
text += ' value="' + this.textUtils.escapeHTML(p.value) + '"/>\n';
|
|
});
|
|
text += '</form>\n';
|
|
|
|
// Add an in-line script to automatically submit the form.
|
|
text += '<script type="text/javascript"> \n' +
|
|
' window.onload = function() { \n' +
|
|
' document.ltiLaunchForm.submit(); \n' +
|
|
' }; \n' +
|
|
'</script> \n';
|
|
|
|
return this.fileProvider.writeFile(this.LAUNCHER_FILE_NAME, text).then((entry) => {
|
|
if (this.appProvider.isDesktop()) {
|
|
return entry.toInternalURL();
|
|
} else {
|
|
return entry.toURL();
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Get a LTI.
|
|
*
|
|
* @param {number} courseId Course ID.
|
|
* @param {number} cmId Course module ID.
|
|
* @return {Promise<any>} Promise resolved when the LTI is retrieved.
|
|
*/
|
|
getLti(courseId: number, cmId: number): Promise<any> {
|
|
const params: any = {
|
|
courseids: [courseId]
|
|
};
|
|
const preSets: any = {
|
|
cacheKey: this.getLtiCacheKey(courseId),
|
|
updateFrequency: CoreSite.FREQUENCY_RARELY
|
|
};
|
|
|
|
return this.sitesProvider.getCurrentSite().read('mod_lti_get_ltis_by_courses', params, preSets).then((response) => {
|
|
if (response.ltis) {
|
|
const currentLti = response.ltis.find((lti) => lti.coursemodule == cmId);
|
|
if (currentLti) {
|
|
return currentLti;
|
|
}
|
|
}
|
|
|
|
return Promise.reject(null);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Get cache key for LTI data WS calls.
|
|
*
|
|
* @param {number} courseId Course ID.
|
|
* @return {string} Cache key.
|
|
*/
|
|
protected getLtiCacheKey(courseId: number): string {
|
|
return this.ROOT_CACHE_KEY + 'lti:' + courseId;
|
|
}
|
|
|
|
/**
|
|
* Get a LTI launch data.
|
|
*
|
|
* @param {number} id LTI id.
|
|
* @return {Promise<any>} Promise resolved when the launch data is retrieved.
|
|
*/
|
|
getLtiLaunchData(id: number): Promise<any> {
|
|
const params: any = {
|
|
toolid: id
|
|
};
|
|
|
|
// Try to avoid using cache since the "nonce" parameter is set to a timestamp.
|
|
const preSets = {
|
|
getFromCache: false,
|
|
saveToCache: true,
|
|
emergencyCache: true,
|
|
cacheKey: this.getLtiLaunchDataCacheKey(id)
|
|
};
|
|
|
|
return this.sitesProvider.getCurrentSite().read('mod_lti_get_tool_launch_data', params, preSets).then((response) => {
|
|
if (response.endpoint) {
|
|
return response;
|
|
}
|
|
|
|
return Promise.reject(null);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Get cache key for LTI launch data WS calls.
|
|
*
|
|
* @param {number} id LTI id.
|
|
* @return {string} Cache key.
|
|
*/
|
|
protected getLtiLaunchDataCacheKey(id: number): string {
|
|
return this.ROOT_CACHE_KEY + 'launch:' + id;
|
|
}
|
|
|
|
/**
|
|
* Invalidates LTI data.
|
|
*
|
|
* @param {number} courseId Course ID.
|
|
* @return {Promise<any>} Promise resolved when the data is invalidated.
|
|
*/
|
|
invalidateLti(courseId: number): Promise<any> {
|
|
return this.sitesProvider.getCurrentSite().invalidateWsCacheForKey(this.getLtiCacheKey(courseId));
|
|
}
|
|
|
|
/**
|
|
* Invalidates options.
|
|
*
|
|
* @param {number} id LTI id.
|
|
* @return {Promise<any>} Promise resolved when the data is invalidated.
|
|
*/
|
|
invalidateLtiLaunchData(id: number): Promise<any> {
|
|
return this.sitesProvider.getCurrentSite().invalidateWsCacheForKey(this.getLtiLaunchDataCacheKey(id));
|
|
}
|
|
|
|
/**
|
|
* Launch LTI.
|
|
*
|
|
* @param {string} url Launch URL.
|
|
* @param {AddonModLtiParam[]} params Launch params.
|
|
* @return {Promise<any>} Promise resolved when the WS call is successful.
|
|
*/
|
|
launch(url: string, params: AddonModLtiParam[]): Promise<any> {
|
|
if (!this.urlUtils.isHttpURL(url)) {
|
|
return Promise.reject(this.translate.instant('addon.mod_lti.errorinvalidlaunchurl'));
|
|
}
|
|
|
|
// Generate launcher and open it.
|
|
return this.generateLauncher(url, params).then((url) => {
|
|
this.utils.openInApp(url);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Report the LTI as being viewed.
|
|
*
|
|
* @param {string} id LTI id.
|
|
* @param {string} [name] Name of the lti.
|
|
* @param {string} [siteId] Site ID. If not defined, current site.
|
|
* @return {Promise<any>} Promise resolved when the WS call is successful.
|
|
*/
|
|
logView(id: number, name?: string, siteId?: string): Promise<any> {
|
|
const params: any = {
|
|
ltiid: id
|
|
};
|
|
|
|
return this.logHelper.logSingle('mod_lti_view_lti', params, AddonModLtiProvider.COMPONENT, id, name, 'lti', {}, siteId);
|
|
}
|
|
}
|