207 lines
7.2 KiB
TypeScript
Raw Normal View History

2021-04-06 16:20:26 +02:00
// (C) Copyright 2015 Moodle Pty Ltd.
//
// 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 { CoreCourseActivityPrefetchHandlerBase } from '@features/course/classes/activity-prefetch-handler';
import { CoreCourseAnyModuleData } from '@features/course/services/course';
import { CoreCourseHelper } from '@features/course/services/course-helper';
import { CoreFilepool } from '@services/filepool';
import { CoreGroups } from '@services/groups';
import { CoreFileSizeSum, CorePluginFileDelegate } from '@services/plugin-file-delegate';
import { CoreSites, CoreSitesCommonWSOptions, CoreSitesReadingStrategy } from '@services/sites';
import { CoreUtils } from '@services/utils/utils';
import { CoreWSExternalFile } from '@services/ws';
import { makeSingleton } from '@singletons';
import { AddonModWiki, AddonModWikiProvider, AddonModWikiSubwikiPage } from '../wiki';
import { AddonModWikiSync, AddonModWikiSyncWikiResult } from '../wiki-sync';
/**
* Handler to prefetch wikis.
*/
@Injectable({ providedIn: 'root' })
export class AddonModWikiPrefetchHandlerService extends CoreCourseActivityPrefetchHandlerBase {
name = 'AddonModWiki';
modName = 'wiki';
component = AddonModWikiProvider.COMPONENT;
updatesNames = /^.*files$|^pages$/;
/**
* Returns a list of pages that can be downloaded.
*
* @param module The module object returned by WS.
* @param courseId The course ID.
* @param options Other options.
* @return List of pages.
*/
protected async getAllPages(
module: CoreCourseAnyModuleData,
courseId: number,
options: CoreSitesCommonWSOptions = {},
): Promise<AddonModWikiSubwikiPage[]> {
options.siteId = options.siteId || CoreSites.getCurrentSiteId();
try {
const wiki = await AddonModWiki.getWiki(courseId, module.id, options);
return await AddonModWiki.getWikiPageList(wiki, options);
} catch {
// Wiki not found, return empty list.
return [];
}
}
/**
* @inheritdoc
*/
async getDownloadSize(module: CoreCourseAnyModuleData, courseId: number, single?: boolean): Promise<CoreFileSizeSum> {
const promises: Promise<CoreFileSizeSum>[] = [];
const siteId = CoreSites.getCurrentSiteId();
promises.push(this.getFiles(module, courseId, single, siteId).then((files) =>
CorePluginFileDelegate.getFilesDownloadSize(files)));
promises.push(this.getAllPages(module, courseId, {
readingStrategy: CoreSitesReadingStrategy.OnlyNetwork,
siteId,
}).then((pages) => {
let size = 0;
pages.forEach((page) => {
if (page.contentsize) {
size = size + page.contentsize;
}
});
return { size: size, total: true };
}));
const sizes = await Promise.all(promises);
return {
size: sizes[0].size + sizes[1].size,
total: sizes[0].total && sizes[1].total,
};
}
/**
* @inheritdoc
*/
async getFiles(
module: CoreCourseAnyModuleData,
courseId: number,
single?: boolean,
siteId?: string,
): Promise<CoreWSExternalFile[]> {
siteId = siteId || CoreSites.getCurrentSiteId();
try {
const wiki = await AddonModWiki.getWiki(courseId, module.id, { siteId });
const introFiles = this.getIntroFilesFromInstance(module, wiki);
const files = await AddonModWiki.getWikiFileList(wiki, { siteId });
return introFiles.concat(files);
} catch {
// Wiki not found, return empty list.
return [];
}
}
/**
* @inheritdoc
*/
invalidateContent(moduleId: number, courseId: number): Promise<void> {
return AddonModWiki.invalidateContent(moduleId, courseId);
}
/**
* @inheritdoc
*/
async prefetch(module: CoreCourseAnyModuleData, courseId?: number, single?: boolean): Promise<void> {
// Get the download time of the package before starting the download (otherwise we'd always get current time).
const siteId = CoreSites.getCurrentSiteId();
const data = await CoreUtils.ignoreErrors(CoreFilepool.getPackageData(siteId, this.component, module.id));
const downloadTime = data?.downloadTime || 0;
return this.prefetchPackage(module, courseId, this.prefetchWiki.bind(this, module, courseId, single, downloadTime, siteId));
}
/**
* Prefetch a wiki.
*
* @param module Module.
* @param courseId Course ID the module belongs to.
* @param single True if we're downloading a single module, false if we're downloading a whole section.
* @param downloadTime The previous download time, 0 if no previous download.
* @param siteId Site ID.
* @return Promise resolved when done.
*/
protected async prefetchWiki(
module: CoreCourseAnyModuleData,
courseId: number,
single: boolean,
downloadTime: number,
siteId: string,
): Promise<void> {
const userId = CoreSites.getCurrentSiteUserId();
const commonOptions = {
readingStrategy: CoreSitesReadingStrategy.OnlyNetwork,
siteId,
};
const modOptions = {
cmId: module.id,
...commonOptions, // Include all common options.
};
// Get the list of pages.
const pages = await this.getAllPages(module, courseId, commonOptions);
const promises: Promise<unknown>[] = [];
pages.forEach((page) => {
// Fetch page contents if it needs to be fetched.
if (page.timemodified > downloadTime) {
promises.push(AddonModWiki.getPageContents(page.id, modOptions));
}
});
// Fetch group data.
promises.push(CoreGroups.getActivityGroupInfo(module.id, false, userId, siteId));
// Fetch info to provide wiki links.
promises.push(AddonModWiki.getWiki(courseId, module.id, { siteId }).then((wiki) =>
CoreCourseHelper.getModuleCourseIdByInstance(wiki.id, 'wiki', siteId)));
// Get related page files and fetch them.
promises.push(this.getFiles(module, courseId, single, siteId).then((files) =>
CoreFilepool.addFilesToQueue(siteId, files, this.component, module.id)));
await Promise.all(promises);
}
/**
* @inheritdoc
*/
sync(module: CoreCourseAnyModuleData, courseId: number, siteId?: string): Promise<AddonModWikiSyncWikiResult> {
return AddonModWikiSync.syncWiki(module.instance!, module.course, module.id, siteId);
}
}
export const AddonModWikiPrefetchHandler = makeSingleton(AddonModWikiPrefetchHandlerService);