MOBILE-2235 h5p: Support and use isEnabled function in file delegate

main
Dani Palou 2019-12-09 15:34:08 +01:00
parent 40fc0e2b00
commit e0849668e3
18 changed files with 160 additions and 70 deletions

View File

@ -47,4 +47,13 @@ export class AddonModFolderPluginFileHandler implements CorePluginFileHandler {
// Component + Filearea + Revision
return '/mod_folder/content/0/';
}
/**
* Whether or not the handler is enabled on a site level.
*
* @return Whether or not the handler is enabled on a site level.
*/
isEnabled(): boolean | Promise<boolean> {
return true;
}
}

View File

@ -96,7 +96,7 @@ export class AddonModForumPrefetchHandler extends CoreCourseActivityPrefetchHand
if (getInlineFiles && post.messageinlinefiles && post.messageinlinefiles.length) {
files = files.concat(post.messageinlinefiles);
} else if (post.message && !getInlineFiles) {
files = files.concat(this.domUtils.extractDownloadableFilesFromHtmlAsFakeFileObjects(post.message));
files = files.concat(this.filepoolProvider.extractDownloadableFilesFromHtmlAsFakeFileObjects(post.message));
}
});

View File

@ -93,7 +93,7 @@ export class AddonModGlossaryPrefetchHandler extends CoreCourseActivityPrefetchH
if (getInlineFiles && entry.definitioninlinefiles && entry.definitioninlinefiles.length) {
files = files.concat(entry.definitioninlinefiles);
} else if (entry.definition && !getInlineFiles) {
files = files.concat(this.domUtils.extractDownloadableFilesFromHtmlAsFakeFileObjects(entry.definition));
files = files.concat(this.filepoolProvider.extractDownloadableFilesFromHtmlAsFakeFileObjects(entry.definition));
}
});

View File

@ -54,4 +54,13 @@ export class AddonModImscpPluginFileHandler implements CorePluginFileHandler {
// Component + Filearea + Revision
return '/mod_imscp/' + args[2] + '/0/';
}
/**
* Whether or not the handler is enabled on a site level.
*
* @return Whether or not the handler is enabled on a site level.
*/
isEnabled(): boolean | Promise<boolean> {
return true;
}
}

View File

@ -419,7 +419,8 @@ export class AddonModLessonPrefetchHandler extends CoreCourseActivityPrefetchHan
return;
}
answerPage.answerdata.answers.forEach((answer) => {
files.push(...this.domUtils.extractDownloadableFilesFromHtmlAsFakeFileObjects(answer[0]));
files.push(...this.filepoolProvider.extractDownloadableFilesFromHtmlAsFakeFileObjects(
answer[0]));
});
});

View File

@ -47,4 +47,13 @@ export class AddonModPagePluginFileHandler implements CorePluginFileHandler {
// Component + Filearea + Revision
return '/mod_page/content/0/';
}
/**
* Whether or not the handler is enabled on a site level.
*
* @return Whether or not the handler is enabled on a site level.
*/
isEnabled(): boolean | Promise<boolean> {
return true;
}
}

View File

@ -126,7 +126,7 @@ export class AddonModQuizPrefetchHandler extends CoreCourseActivityPrefetchHandl
files = files.concat(feedback.feedbackinlinefiles);
} else if (feedback.feedbacktext && !getInlineFiles) {
files = files.concat(
this.domUtils.extractDownloadableFilesFromHtmlAsFakeFileObjects(feedback.feedbacktext));
this.filepoolProvider.extractDownloadableFilesFromHtmlAsFakeFileObjects(feedback.feedbacktext));
}
}));
}

View File

@ -47,4 +47,13 @@ export class AddonModResourcePluginFileHandler implements CorePluginFileHandler
// Component + Filearea + Revision
return '/mod_resource/content/0/';
}
/**
* Whether or not the handler is enabled on a site level.
*
* @return Whether or not the handler is enabled on a site level.
*/
isEnabled(): boolean | Promise<boolean> {
return true;
}
}

View File

@ -47,4 +47,13 @@ export class AddonModScormPluginFileHandler implements CorePluginFileHandler {
// Component + Filearea + Revision
return '/mod_scorm/content/0/';
}
/**
* Whether or not the handler is enabled on a site level.
*
* @return Whether or not the handler is enabled on a site level.
*/
isEnabled(): boolean | Promise<boolean> {
return true;
}
}

View File

@ -237,14 +237,16 @@ export class CoreDelegate {
* @return True when registered, false if already registered.
*/
registerHandler(handler: CoreDelegateHandler): boolean {
if (typeof this.handlers[handler[this.handlerNameProperty]] !== 'undefined') {
const key = handler[this.handlerNameProperty] || handler.name;
if (typeof this.handlers[key] !== 'undefined') {
this.logger.log(`Handler '${handler[this.handlerNameProperty]}' already registered`);
return false;
}
this.logger.log(`Registered handler '${handler[this.handlerNameProperty]}'`);
this.handlers[handler[this.handlerNameProperty]] = handler;
this.handlers[key] = handler;
return true;
}
@ -282,10 +284,12 @@ export class CoreDelegate {
}).then((enabled: boolean) => {
// Check that site hasn't changed since the check started.
if (this.sitesProvider.getCurrentSiteId() === siteId) {
const key = handler[this.handlerNameProperty] || handler.name;
if (enabled) {
this.enabledHandlers[handler[this.handlerNameProperty]] = handler;
this.enabledHandlers[key] = handler;
} else {
delete this.enabledHandlers[handler[this.handlerNameProperty]];
delete this.enabledHandlers[key];
}
}
}).finally(() => {

View File

@ -195,12 +195,12 @@ export class CoreCourseModulePrefetchHandlerBase implements CoreCourseModulePref
if (typeof instance.introfiles != 'undefined') {
return instance.introfiles;
} else if (instance.intro) {
return this.domUtils.extractDownloadableFilesFromHtmlAsFakeFileObjects(instance.intro);
return this.filepoolProvider.extractDownloadableFilesFromHtmlAsFakeFileObjects(instance.intro);
}
}
if (module.description) {
return this.domUtils.extractDownloadableFilesFromHtmlAsFakeFileObjects(module.description);
return this.filepoolProvider.extractDownloadableFilesFromHtmlAsFakeFileObjects(module.description);
}
return [];

View File

@ -438,7 +438,7 @@ export class CoreCourseHelperProvider {
sizePromise = this.prefetchDelegate.getDownloadSize(section.modules, courseId);
// Check if the section has embedded files in the description.
haveEmbeddedFiles = this.domUtils.extractDownloadableFilesFromHtml(section.summary).length > 0;
haveEmbeddedFiles = this.filepoolProvider.extractDownloadableFilesFromHtml(section.summary).length > 0;
} else {
const promises = [],
results = {
@ -454,7 +454,7 @@ export class CoreCourseHelperProvider {
}));
// Check if the section has embedded files in the description.
if (!haveEmbeddedFiles && this.domUtils.extractDownloadableFilesFromHtml(s.summary).length > 0) {
if (!haveEmbeddedFiles && this.filepoolProvider.extractDownloadableFilesFromHtml(s.summary).length > 0) {
haveEmbeddedFiles = true;
}
}
@ -1449,7 +1449,7 @@ export class CoreCourseHelperProvider {
}));
// Download the files in the section description.
const introFiles = this.domUtils.extractDownloadableFilesFromHtmlAsFakeFileObjects(section.summary),
const introFiles = this.filepoolProvider.extractDownloadableFilesFromHtmlAsFakeFileObjects(section.summary),
siteId = this.sitesProvider.getCurrentSiteId();
promises.push(this.filepoolProvider.addFilesToQueue(siteId, introFiles, CoreCourseProvider.COMPONENT, courseId)

View File

@ -63,7 +63,7 @@ export class CoreH5PPluginFileHandler implements CorePluginFileHandler {
/**
* Given an HTML element, get the URLs of the files that should be downloaded and weren't treated by
* CoreDomUtilsProvider.extractDownloadableFilesFromHtml.
* CoreFilepoolProvider.extractDownloadableFilesFromHtml.
*
* @param container Container where to get the URLs from.
* @return {string[]} List of URLs.
@ -103,6 +103,15 @@ export class CoreH5PPluginFileHandler implements CorePluginFileHandler {
});
}
/**
* Whether or not the handler is enabled on a site level.
*
* @return Whether or not the handler is enabled on a site level.
*/
isEnabled(): boolean | Promise<boolean> {
return this.h5pProvider.canGetTrustedH5PFileInSite();
}
/**
* Check whether the file should be treated by this handler. It is used in functions where the component isn't used.
*

View File

@ -516,7 +516,7 @@ export class CoreQuestionHelperProvider {
*/
prefetchQuestionFiles(question: any, component?: string, componentId?: string | number, siteId?: string, usageId?: number)
: Promise<any> {
const urls = this.domUtils.extractDownloadableFilesFromHtml(question.html);
const urls = this.filepoolProvider.extractDownloadableFilesFromHtml(question.html);
if (!component) {
component = CoreQuestionProvider.COMPONENT;

View File

@ -1239,6 +1239,59 @@ export class CoreFilepoolProvider {
}
}
/**
* Extract the downloadable URLs from an HTML code.
*
* @param html HTML code.
* @return List of file urls.
*/
extractDownloadableFilesFromHtml(html: string): string[] {
let urls = [],
elements;
const element = this.domUtils.convertToElement(html);
elements = element.querySelectorAll('a, img, audio, video, source, track');
for (let i = 0; i < elements.length; i++) {
const element = elements[i];
let url = element.tagName === 'A' ? element.href : element.src;
if (url && this.urlUtils.isDownloadableUrl(url) && urls.indexOf(url) == -1) {
urls.push(url);
}
// Treat video poster.
if (element.tagName == 'VIDEO' && element.getAttribute('poster')) {
url = element.getAttribute('poster');
if (url && this.urlUtils.isDownloadableUrl(url) && urls.indexOf(url) == -1) {
urls.push(url);
}
}
}
// Now get other files from plugin file handlers.
urls = urls.concat(this.pluginFileDelegate.getDownloadableFilesFromHTML(element));
return urls;
}
/**
* Extract the downloadable URLs from an HTML code and returns them in fake file objects.
*
* @param html HTML code.
* @return List of fake file objects with file URLs.
*/
extractDownloadableFilesFromHtmlAsFakeFileObjects(html: string): any[] {
const urls = this.extractDownloadableFilesFromHtml(html);
// Convert them to fake file objects.
return urls.map((url) => {
return {
fileurl: url
};
});
}
/**
* Fill Missing Extension In the File Object if needed.
* This is to migrate from old versions.

View File

@ -13,18 +13,17 @@
// limitations under the License.
import { Injectable } from '@angular/core';
import { CoreEventsProvider } from './events';
import { CoreLoggerProvider } from './logger';
import { CoreSitesProvider } from './sites';
import { CoreWSExternalFile } from '@providers/ws';
import { FileEntry } from '@ionic-native/file';
import { CoreDelegate, CoreDelegateHandler } from '@classes/delegate';
/**
* Interface that all plugin file handlers must implement.
*/
export interface CorePluginFileHandler {
/**
* A name to identify the handler.
*/
name: string;
export interface CorePluginFileHandler extends CoreDelegateHandler {
/**
* The "component" of the handler. It should match the "component" of pluginfile URLs.
@ -69,7 +68,7 @@ export interface CorePluginFileHandler {
/**
* Given an HTML element, get the URLs of the files that should be downloaded and weren't treated by
* CoreDomUtilsProvider.extractDownloadableFilesFromHtml.
* CoreFilepoolProvider.extractDownloadableFilesFromHtml.
*
* @param container Container where to get the URLs from.
* @return {string[]} List of URLs.
@ -108,12 +107,13 @@ export interface CorePluginFileHandler {
* Delegate to register pluginfile information handlers.
*/
@Injectable()
export class CorePluginFileDelegate {
protected logger;
protected handlers: { [s: string]: CorePluginFileHandler } = {};
export class CorePluginFileDelegate extends CoreDelegate {
protected handlerNameProperty = 'component';
constructor(logger: CoreLoggerProvider) {
this.logger = logger.getInstance('CorePluginFileDelegate');
constructor(loggerProvider: CoreLoggerProvider,
sitesProvider: CoreSitesProvider,
eventsProvider: CoreEventsProvider) {
super('CorePluginFileDelegate', loggerProvider, sitesProvider, eventsProvider);
}
/**
@ -167,18 +167,6 @@ export class CorePluginFileDelegate {
return Promise.resolve(file);
}
/**
* Get the handler for a certain pluginfile url.
*
* @param component Component of the plugin.
* @return Handler. Undefined if no handler found for the plugin.
*/
protected getPluginHandler(component: string): CorePluginFileHandler {
if (typeof this.handlers[component] != 'undefined') {
return this.handlers[component];
}
}
/**
* Get the RegExp of the component and filearea described in the URL.
*
@ -187,7 +175,7 @@ export class CorePluginFileDelegate {
*/
getComponentRevisionRegExp(args: string[]): RegExp {
// Get handler based on component (args[1]).
const handler = this.getPluginHandler(args[1]);
const handler = <CorePluginFileHandler> this.getHandler(args[1], true);
if (handler && handler.getComponentRevisionRegExp) {
return handler.getComponentRevisionRegExp(args);
@ -196,7 +184,7 @@ export class CorePluginFileDelegate {
/**
* Given an HTML element, get the URLs of the files that should be downloaded and weren't treated by
* CoreDomUtilsProvider.extractDownloadableFilesFromHtml.
* CoreFilepoolProvider.extractDownloadableFilesFromHtml.
*
* @param container Container where to get the URLs from.
* @return List of URLs.
@ -204,8 +192,8 @@ export class CorePluginFileDelegate {
getDownloadableFilesFromHTML(container: HTMLElement): string[] {
let files = [];
for (const component in this.handlers) {
const handler = this.handlers[component];
for (const component in this.enabledHandlers) {
const handler = <CorePluginFileHandler> this.enabledHandlers[component];
if (handler && handler.getDownloadableFilesFromHTML) {
files = files.concat(handler.getDownloadableFilesFromHTML(container));
@ -278,8 +266,8 @@ export class CorePluginFileDelegate {
* @return Handler.
*/
protected getHandlerForFile(file: CoreWSExternalFile): CorePluginFileHandler {
for (const component in this.handlers) {
const handler = this.handlers[component];
for (const component in this.enabledHandlers) {
const handler = <CorePluginFileHandler> this.enabledHandlers[component];
if (handler && handler.shouldHandleFile && handler.shouldHandleFile(file)) {
return handler;
@ -287,25 +275,6 @@ export class CorePluginFileDelegate {
}
}
/**
* Register a handler.
*
* @param handler The handler to register.
* @return True if registered successfully, false otherwise.
*/
registerHandler(handler: CorePluginFileHandler): boolean {
if (typeof this.handlers[handler.component || handler.name] !== 'undefined') {
this.logger.log(`Handler '${handler.component}' already registered`);
return false;
}
this.logger.log(`Registered handler '${handler.component}'`);
this.handlers[handler.component || handler.name] = handler;
return true;
}
/**
* Removes the revision number from a file URL.
*
@ -315,7 +284,7 @@ export class CorePluginFileDelegate {
*/
removeRevisionFromUrl(url: string, args: string[]): string {
// Get handler based on component (args[1]).
const handler = this.getPluginHandler(args[1]);
const handler = <CorePluginFileHandler> this.getHandler(args[1], true);
if (handler && handler.getComponentRevisionRegExp && handler.getComponentRevisionReplace) {
const revisionRegex = handler.getComponentRevisionRegExp(args);

View File

@ -22,7 +22,7 @@ import { TranslateService } from '@ngx-translate/core';
import { CoreTextUtilsProvider } from './text';
import { CoreAppProvider } from '../app';
import { CoreConfigProvider } from '../config';
import { CorePluginFileDelegate } from '../plugin-file-delegate';
import { CoreLoggerProvider } from '../logger';
import { CoreUrlUtilsProvider } from './url';
import { CoreFileProvider } from '@providers/file';
import { CoreConstants } from '@core/constants';
@ -62,6 +62,7 @@ export class CoreDomUtilsProvider {
protected lastInstanceId = 0;
protected debugDisplay = false; // Whether to display debug messages. Store it in a variable to make it synchronous.
protected displayedAlerts = {}; // To prevent duplicated alerts.
protected logger;
constructor(private translate: TranslateService,
private loadingCtrl: LoadingController,
@ -76,7 +77,9 @@ export class CoreDomUtilsProvider {
private sanitizer: DomSanitizer,
private popoverCtrl: PopoverController,
private fileProvider: CoreFileProvider,
private pluginFileDelegate: CorePluginFileDelegate) {
loggerProvider: CoreLoggerProvider) {
this.logger = loggerProvider.getInstance('CoreDomUtilsProvider');
// Check if debug messages should be displayed.
configProvider.get(CoreConstants.SETTINGS_DEBUG_DISPLAY, false).then((debugDisplay) => {
@ -260,9 +263,13 @@ export class CoreDomUtilsProvider {
*
* @param html HTML code.
* @return List of file urls.
* @deprecated since 3.8. Use CoreFilepoolProvider.extractDownloadableFilesFromHtml instead.
*/
extractDownloadableFilesFromHtml(html: string): string[] {
let urls = [];
this.logger.error('The function extractDownloadableFilesFromHtml has been moved to CoreFilepoolProvider.' +
' Please use that function instead of this one.');
const urls = [];
let elements;
const element = this.convertToElement(html);
@ -285,9 +292,6 @@ export class CoreDomUtilsProvider {
}
}
// Now get other files from plugin file handlers.
urls = urls.concat(this.pluginFileDelegate.getDownloadableFilesFromHTML(element));
return urls;
}
@ -296,6 +300,7 @@ export class CoreDomUtilsProvider {
*
* @param html HTML code.
* @return List of fake file objects with file URLs.
* @deprecated since 3.8. Use CoreFilepoolProvider.extractDownloadableFilesFromHtmlAsFakeFileObjects instead.
*/
extractDownloadableFilesFromHtmlAsFakeFileObjects(html: string): any[] {
const urls = this.extractDownloadableFilesFromHtml(html);

View File

@ -1,6 +1,10 @@
This files describes API changes in the Moodle Mobile app,
information provided here is intended especially for developers.
=== 3.8.0 ===
- CoreDomUtilsProvider.extractDownloadableFilesFromHtml and CoreDomUtilsProvider.extractDownloadableFilesFromHtmlAsFakeFileObjects have been deprecated. Please use CoreFilepoolProvider.extractDownloadableFilesFromHtml and CoreFilepoolProvider.extractDownloadableFilesFromHtmlAsFakeFileObjects. We had to move them to prevent a circular dependency.
=== 3.7.1 ===
- CoreGroupsProvider.getActivityAllowedGroups and CoreGroupsProvider.getActivityAllowedGroupsIfEnabled now return the full response of core_group_get_activity_allowed_groups instead of just the groups.