Merge pull request #2310 from dpalou/MOBILE-3298
MOBILE-3298 course: Don't fail module download if avatar failsmain
commit
14a963cf6d
|
@ -354,15 +354,7 @@ export class AddonModAssignPrefetchHandler extends CoreCourseActivityPrefetchHan
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
// Participiants already fetched, we don't need to ignore cache now.
|
// Participiants already fetched, we don't need to ignore cache now.
|
||||||
return this.assignHelper.getParticipants(assign, group.id, false, siteId).then((participants) => {
|
return this.assignHelper.getParticipants(assign, group.id, false, siteId).then((participants) => {
|
||||||
const promises = [];
|
return this.userProvider.prefetchUserAvatars(participants, 'profileimageurl', siteId);
|
||||||
|
|
||||||
participants.forEach((participant) => {
|
|
||||||
if (participant.profileimageurl) {
|
|
||||||
promises.push(this.filepoolProvider.addToQueueByUrl(siteId, participant.profileimageurl));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return Promise.all(promises);
|
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
// Fail silently (Moodle < 3.2).
|
// Fail silently (Moodle < 3.2).
|
||||||
});
|
});
|
||||||
|
|
|
@ -182,9 +182,7 @@ export class AddonModChatPrefetchHandler extends CoreCourseActivityPrefetchHandl
|
||||||
});
|
});
|
||||||
const userIds = Object.keys(users).map(Number);
|
const userIds = Object.keys(users).map(Number);
|
||||||
|
|
||||||
return this.userProvider.prefetchProfiles(userIds, courseId, siteId).catch(() => {
|
return this.userProvider.prefetchProfiles(userIds, courseId, siteId);
|
||||||
// Ignore errors, some users might not exist.
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -244,13 +244,14 @@ export class AddonModForumProvider {
|
||||||
* Check if a user can post to all groups.
|
* Check if a user can post to all groups.
|
||||||
*
|
*
|
||||||
* @param forumId Forum ID.
|
* @param forumId Forum ID.
|
||||||
|
* @param siteId Site ID. If not defined, current site.
|
||||||
* @return Promise resolved with an object with the following properties:
|
* @return Promise resolved with an object with the following properties:
|
||||||
* - status (boolean)
|
* - status (boolean)
|
||||||
* - canpindiscussions (boolean)
|
* - canpindiscussions (boolean)
|
||||||
* - cancreateattachment (boolean)
|
* - cancreateattachment (boolean)
|
||||||
*/
|
*/
|
||||||
canAddDiscussionToAll(forumId: number): Promise<any> {
|
canAddDiscussionToAll(forumId: number, siteId?: string): Promise<any> {
|
||||||
return this.canAddDiscussion(forumId, AddonModForumProvider.ALL_PARTICIPANTS);
|
return this.canAddDiscussion(forumId, AddonModForumProvider.ALL_PARTICIPANTS, siteId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -107,12 +107,13 @@ export class AddonModForumPrefetchHandler extends CoreCourseActivityPrefetchHand
|
||||||
* Get the posts to be prefetched.
|
* Get the posts to be prefetched.
|
||||||
*
|
*
|
||||||
* @param forum Forum instance.
|
* @param forum Forum instance.
|
||||||
|
* @param siteId Site ID. If not defined, current site.
|
||||||
* @return Promise resolved with array of posts.
|
* @return Promise resolved with array of posts.
|
||||||
*/
|
*/
|
||||||
protected getPostsForPrefetch(forum: any): Promise<any[]> {
|
protected getPostsForPrefetch(forum: any, siteId?: string): Promise<any[]> {
|
||||||
const promises = this.forumProvider.getAvailableSortOrders().map((sortOrder) => {
|
const promises = this.forumProvider.getAvailableSortOrders().map((sortOrder) => {
|
||||||
// Get discussions in first 2 pages.
|
// Get discussions in first 2 pages.
|
||||||
return this.forumProvider.getDiscussionsInPages(forum.id, sortOrder.value, false, 2).then((response) => {
|
return this.forumProvider.getDiscussionsInPages(forum.id, sortOrder.value, false, 2, 0, siteId).then((response) => {
|
||||||
if (response.error) {
|
if (response.error) {
|
||||||
return Promise.reject(null);
|
return Promise.reject(null);
|
||||||
}
|
}
|
||||||
|
@ -120,7 +121,7 @@ export class AddonModForumPrefetchHandler extends CoreCourseActivityPrefetchHand
|
||||||
const promises = [];
|
const promises = [];
|
||||||
|
|
||||||
response.discussions.forEach((discussion) => {
|
response.discussions.forEach((discussion) => {
|
||||||
promises.push(this.forumProvider.getDiscussionPosts(discussion.discussion));
|
promises.push(this.forumProvider.getDiscussionPosts(discussion.discussion, siteId));
|
||||||
});
|
});
|
||||||
|
|
||||||
return Promise.all(promises);
|
return Promise.all(promises);
|
||||||
|
@ -200,41 +201,31 @@ export class AddonModForumPrefetchHandler extends CoreCourseActivityPrefetchHand
|
||||||
*/
|
*/
|
||||||
protected prefetchForum(module: any, courseId: number, single: boolean, siteId: string): Promise<any> {
|
protected prefetchForum(module: any, courseId: number, single: boolean, siteId: string): Promise<any> {
|
||||||
// Get the forum data.
|
// Get the forum data.
|
||||||
return this.forumProvider.getForum(courseId, module.id).then((forum) => {
|
return this.forumProvider.getForum(courseId, module.id, siteId).then((forum) => {
|
||||||
const promises = [];
|
const promises = [];
|
||||||
|
|
||||||
// Prefetch the posts.
|
// Prefetch the posts.
|
||||||
promises.push(this.getPostsForPrefetch(forum).then((posts) => {
|
promises.push(this.getPostsForPrefetch(forum, siteId).then((posts) => {
|
||||||
const promises = [];
|
const promises = [];
|
||||||
|
|
||||||
// Gather user profile images.
|
const files = this.getIntroFilesFromInstance(module, forum).concat(this.getPostsFiles(posts));
|
||||||
const avatars = {}; // List of user avatars, preventing duplicates.
|
|
||||||
|
|
||||||
posts.forEach((post) => {
|
|
||||||
if (post.userpictureurl) {
|
|
||||||
avatars[post.userpictureurl] = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Prefetch intro files, attachments, embedded files and user avatars.
|
|
||||||
const avatarFiles = Object.keys(avatars).map((url) => {
|
|
||||||
return { fileurl: url };
|
|
||||||
});
|
|
||||||
const files = this.getIntroFilesFromInstance(module, forum).concat(this.getPostsFiles(posts)).concat(avatarFiles);
|
|
||||||
promises.push(this.filepoolProvider.addFilesToQueue(siteId, files, this.component, module.id));
|
promises.push(this.filepoolProvider.addFilesToQueue(siteId, files, this.component, module.id));
|
||||||
|
|
||||||
// Prefetch groups data.
|
// Prefetch groups data.
|
||||||
promises.push(this.prefetchGroupsInfo(forum, courseId, forum.cancreatediscussions));
|
promises.push(this.prefetchGroupsInfo(forum, courseId, forum.cancreatediscussions, siteId));
|
||||||
|
|
||||||
|
// Prefetch avatars.
|
||||||
|
promises.push(this.userProvider.prefetchUserAvatars(posts, 'userpictureurl', siteId));
|
||||||
|
|
||||||
return Promise.all(promises);
|
return Promise.all(promises);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Prefetch access information.
|
// Prefetch access information.
|
||||||
promises.push(this.forumProvider.getAccessInformation(forum.id));
|
promises.push(this.forumProvider.getAccessInformation(forum.id, false, siteId));
|
||||||
|
|
||||||
// Prefetch sort order preference.
|
// Prefetch sort order preference.
|
||||||
if (this.forumProvider.isDiscussionListSortingAvailable()) {
|
if (this.forumProvider.isDiscussionListSortingAvailable()) {
|
||||||
promises.push(this.userProvider.getUserPreference(AddonModForumProvider.PREFERENCE_SORTORDER));
|
promises.push(this.userProvider.getUserPreference(AddonModForumProvider.PREFERENCE_SORTORDER, siteId));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.all(promises);
|
return Promise.all(promises);
|
||||||
|
@ -247,30 +238,31 @@ export class AddonModForumPrefetchHandler extends CoreCourseActivityPrefetchHand
|
||||||
* @param module The module object returned by WS.
|
* @param module The module object returned by WS.
|
||||||
* @param courseI Course ID the module belongs to.
|
* @param courseI Course ID the module belongs to.
|
||||||
* @param canCreateDiscussions Whether the user can create discussions in the forum.
|
* @param canCreateDiscussions Whether the user can create discussions in the forum.
|
||||||
|
* @param siteId Site ID. If not defined, current site.
|
||||||
* @return Promise resolved when group data has been prefetched.
|
* @return Promise resolved when group data has been prefetched.
|
||||||
*/
|
*/
|
||||||
protected prefetchGroupsInfo(forum: any, courseId: number, canCreateDiscussions: boolean): any {
|
protected prefetchGroupsInfo(forum: any, courseId: number, canCreateDiscussions: boolean, siteId?: string): any {
|
||||||
// Check group mode.
|
// Check group mode.
|
||||||
return this.groupsProvider.getActivityGroupMode(forum.cmid).then((mode) => {
|
return this.groupsProvider.getActivityGroupMode(forum.cmid, siteId).then((mode) => {
|
||||||
if (mode !== CoreGroupsProvider.SEPARATEGROUPS && mode !== CoreGroupsProvider.VISIBLEGROUPS) {
|
if (mode !== CoreGroupsProvider.SEPARATEGROUPS && mode !== CoreGroupsProvider.VISIBLEGROUPS) {
|
||||||
// Activity doesn't use groups. Prefetch canAddDiscussionToAll to determine if user can pin/attach.
|
// Activity doesn't use groups. Prefetch canAddDiscussionToAll to determine if user can pin/attach.
|
||||||
return this.forumProvider.canAddDiscussionToAll(forum.id).catch(() => {
|
return this.forumProvider.canAddDiscussionToAll(forum.id, siteId).catch(() => {
|
||||||
// Ignore errors.
|
// Ignore errors.
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Activity uses groups, prefetch allowed groups.
|
// Activity uses groups, prefetch allowed groups.
|
||||||
return this.groupsProvider.getActivityAllowedGroups(forum.cmid).then((result) => {
|
return this.groupsProvider.getActivityAllowedGroups(forum.cmid, undefined, siteId).then((result) => {
|
||||||
if (mode === CoreGroupsProvider.SEPARATEGROUPS) {
|
if (mode === CoreGroupsProvider.SEPARATEGROUPS) {
|
||||||
// Groups are already filtered by WS. Prefetch canAddDiscussionToAll to determine if user can pin/attach.
|
// Groups are already filtered by WS. Prefetch canAddDiscussionToAll to determine if user can pin/attach.
|
||||||
return this.forumProvider.canAddDiscussionToAll(forum.id).catch(() => {
|
return this.forumProvider.canAddDiscussionToAll(forum.id, siteId).catch(() => {
|
||||||
// Ignore errors.
|
// Ignore errors.
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (canCreateDiscussions) {
|
if (canCreateDiscussions) {
|
||||||
// Prefetch data to check the visible groups when creating discussions.
|
// Prefetch data to check the visible groups when creating discussions.
|
||||||
return this.forumProvider.canAddDiscussionToAll(forum.id).catch(() => {
|
return this.forumProvider.canAddDiscussionToAll(forum.id, siteId).catch(() => {
|
||||||
// The call failed, let's assume he can't.
|
// The call failed, let's assume he can't.
|
||||||
return {
|
return {
|
||||||
status: false
|
status: false
|
||||||
|
@ -284,7 +276,7 @@ export class AddonModForumPrefetchHandler extends CoreCourseActivityPrefetchHand
|
||||||
// The user can't post to all groups, let's check which groups he can post to.
|
// The user can't post to all groups, let's check which groups he can post to.
|
||||||
const groupPromises = [];
|
const groupPromises = [];
|
||||||
result.groups.forEach((group) => {
|
result.groups.forEach((group) => {
|
||||||
groupPromises.push(this.forumProvider.canAddDiscussion(forum.id, group.id).catch(() => {
|
groupPromises.push(this.forumProvider.canAddDiscussion(forum.id, group.id, siteId).catch(() => {
|
||||||
// Ignore errors.
|
// Ignore errors.
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
|
@ -26,6 +26,7 @@ import { AddonModGlossaryProvider } from './glossary';
|
||||||
import { AddonModGlossarySyncProvider } from './sync';
|
import { AddonModGlossarySyncProvider } from './sync';
|
||||||
import { CoreFilterHelperProvider } from '@core/filter/providers/helper';
|
import { CoreFilterHelperProvider } from '@core/filter/providers/helper';
|
||||||
import { CorePluginFileDelegate } from '@providers/plugin-file-delegate';
|
import { CorePluginFileDelegate } from '@providers/plugin-file-delegate';
|
||||||
|
import { CoreUserProvider } from '@core/user/providers/user';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler to prefetch forums.
|
* Handler to prefetch forums.
|
||||||
|
@ -48,7 +49,8 @@ export class AddonModGlossaryPrefetchHandler extends CoreCourseActivityPrefetchH
|
||||||
pluginFileDelegate: CorePluginFileDelegate,
|
pluginFileDelegate: CorePluginFileDelegate,
|
||||||
protected glossaryProvider: AddonModGlossaryProvider,
|
protected glossaryProvider: AddonModGlossaryProvider,
|
||||||
protected commentsProvider: CoreCommentsProvider,
|
protected commentsProvider: CoreCommentsProvider,
|
||||||
protected syncProvider: AddonModGlossarySyncProvider) {
|
protected syncProvider: AddonModGlossarySyncProvider,
|
||||||
|
protected userProvider: CoreUserProvider) {
|
||||||
|
|
||||||
super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper,
|
super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper,
|
||||||
pluginFileDelegate);
|
pluginFileDelegate);
|
||||||
|
@ -165,35 +167,29 @@ export class AddonModGlossaryPrefetchHandler extends CoreCourseActivityPrefetchH
|
||||||
// Fetch all entries to get information from.
|
// Fetch all entries to get information from.
|
||||||
promises.push(this.glossaryProvider.fetchAllEntries(this.glossaryProvider.getEntriesByLetter,
|
promises.push(this.glossaryProvider.fetchAllEntries(this.glossaryProvider.getEntriesByLetter,
|
||||||
[glossary.id, 'ALL'], false, false, siteId).then((entries) => {
|
[glossary.id, 'ALL'], false, false, siteId).then((entries) => {
|
||||||
const promises = [],
|
const promises = [];
|
||||||
commentsEnabled = !this.commentsProvider.areCommentsDisabledInSite(),
|
const commentsEnabled = !this.commentsProvider.areCommentsDisabledInSite();
|
||||||
avatars = {}; // List of user avatars, preventing duplicates.
|
|
||||||
|
|
||||||
entries.forEach((entry) => {
|
entries.forEach((entry) => {
|
||||||
// Don't fetch individual entries, it's too many WS calls.
|
// Don't fetch individual entries, it's too many WS calls.
|
||||||
|
|
||||||
if (entry.userpictureurl) {
|
|
||||||
avatars[entry.userpictureurl] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (glossary.allowcomments && commentsEnabled) {
|
if (glossary.allowcomments && commentsEnabled) {
|
||||||
promises.push(this.commentsProvider.getComments('module', glossary.coursemodule, 'mod_glossary', entry.id,
|
promises.push(this.commentsProvider.getComments('module', glossary.coursemodule, 'mod_glossary', entry.id,
|
||||||
'glossary_entry', 0, siteId));
|
'glossary_entry', 0, siteId));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Prefetch intro files, entries files and user avatars.
|
const files = this.getFilesFromGlossaryAndEntries(module, glossary, entries);
|
||||||
const avatarFiles = Object.keys(avatars).map((url) => {
|
|
||||||
return { fileurl: url };
|
|
||||||
});
|
|
||||||
const files = this.getFilesFromGlossaryAndEntries(module, glossary, entries).concat(avatarFiles);
|
|
||||||
promises.push(this.filepoolProvider.addFilesToQueue(siteId, files, this.component, module.id));
|
promises.push(this.filepoolProvider.addFilesToQueue(siteId, files, this.component, module.id));
|
||||||
|
|
||||||
|
// Prefetch user avatars.
|
||||||
|
promises.push(this.userProvider.prefetchUserAvatars(entries, 'userpictureurl', siteId));
|
||||||
|
|
||||||
return Promise.all(promises);
|
return Promise.all(promises);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Get all categories.
|
// Get all categories.
|
||||||
promises.push(this.glossaryProvider.getAllCategories(glossary.id));
|
promises.push(this.glossaryProvider.getAllCategories(glossary.id, siteId));
|
||||||
|
|
||||||
// Prefetch data for link handlers.
|
// Prefetch data for link handlers.
|
||||||
promises.push(this.courseProvider.getModuleBasicInfo(module.id, siteId));
|
promises.push(this.courseProvider.getModuleBasicInfo(module.id, siteId));
|
||||||
|
|
|
@ -375,9 +375,7 @@ export class AddonModWorkshopPrefetchHandler extends CoreCourseActivityPrefetchH
|
||||||
});
|
});
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
// Prefetch user profiles.
|
// Prefetch user profiles.
|
||||||
return this.userProvider.prefetchProfiles(userIds, courseId, siteId).catch(() => {
|
return this.userProvider.prefetchProfiles(userIds, courseId, siteId);
|
||||||
// Ignore errors.
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -522,8 +522,10 @@ export class CoreUserProvider {
|
||||||
|
|
||||||
promises.push(this.getProfile(userId, courseId, false, siteId).then((profile) => {
|
promises.push(this.getProfile(userId, courseId, false, siteId).then((profile) => {
|
||||||
if (profile.profileimageurl) {
|
if (profile.profileimageurl) {
|
||||||
this.filepoolProvider.addToQueueByUrl(siteId, profile.profileimageurl);
|
return this.filepoolProvider.addToQueueByUrl(siteId, profile.profileimageurl);
|
||||||
}
|
}
|
||||||
|
}).catch((error) => {
|
||||||
|
this.logger.warn(`Ignore error when prefetching user ${userId}`, error);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -531,6 +533,39 @@ export class CoreUserProvider {
|
||||||
return Promise.all(promises);
|
return Promise.all(promises);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prefetch user avatars. It prevents duplicates.
|
||||||
|
*
|
||||||
|
* @param entries List of entries that have the images.
|
||||||
|
* @param propertyName The name of the property that contains the image.
|
||||||
|
* @param siteId Site ID. If not defined, current site.
|
||||||
|
* @return Promise resolved when prefetched.
|
||||||
|
*/
|
||||||
|
async prefetchUserAvatars(entries: any[], propertyName: string, siteId?: string): Promise<void> {
|
||||||
|
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
||||||
|
|
||||||
|
const treated = {};
|
||||||
|
|
||||||
|
const promises = entries.map(async (entry) => {
|
||||||
|
const imageUrl = entry[propertyName];
|
||||||
|
|
||||||
|
if (!imageUrl || treated[imageUrl]) {
|
||||||
|
// It doesn't have an image or it has already been treated.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
treated[imageUrl] = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await this.filepoolProvider.addToQueueByUrl(siteId, imageUrl);
|
||||||
|
} catch (ex) {
|
||||||
|
this.logger.warn(`Ignore error when prefetching user avatar ${imageUrl}`, entry, ex);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await Promise.all(promises);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search participants in a certain course.
|
* Search participants in a certain course.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue