diff --git a/src/addon/mod/assign/providers/assign-sync.ts b/src/addon/mod/assign/providers/assign-sync.ts index 96627a1cc..561f2245a 100644 --- a/src/addon/mod/assign/providers/assign-sync.ts +++ b/src/addon/mod/assign/providers/assign-sync.ts @@ -216,7 +216,7 @@ export class AddonModAssignSyncProvider extends CoreSyncBaseProvider { courseId = submissions.length > 0 ? submissions[0].courseid : grades[0].courseid; - return this.assignProvider.getAssignmentById(courseId, assignId, siteId).then((assignData) => { + return this.assignProvider.getAssignmentById(courseId, assignId, false, siteId).then((assignData) => { assign = assignData; const promises = []; diff --git a/src/addon/mod/assign/providers/assign.ts b/src/addon/mod/assign/providers/assign.ts index 33d3f0652..7a16d3b11 100644 --- a/src/addon/mod/assign/providers/assign.ts +++ b/src/addon/mod/assign/providers/assign.ts @@ -118,11 +118,12 @@ export class AddonModAssignProvider { * * @param {number} courseId Course ID the assignment belongs to. * @param {number} cmId Assignment module ID. + * @param {boolean} [ignoreCache] True if it should ignore cached data (it will always fail in offline or server down). * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved with the assignment. */ - getAssignment(courseId: number, cmId: number, siteId?: string): Promise { - return this.getAssignmentByField(courseId, 'cmid', cmId, siteId); + getAssignment(courseId: number, cmId: number, ignoreCache?: boolean, siteId?: string): Promise { + return this.getAssignmentByField(courseId, 'cmid', cmId, ignoreCache, siteId); } /** @@ -131,19 +132,27 @@ export class AddonModAssignProvider { * @param {number} courseId Course ID. * @param {string} key Name of the property to check. * @param {any} value Value to search. + * @param {boolean} [ignoreCache] True if it should ignore cached data (it will always fail in offline or server down). * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved when the assignment is retrieved. */ - protected getAssignmentByField(courseId: number, key: string, value: any, siteId?: string): Promise { + protected getAssignmentByField(courseId: number, key: string, value: any, ignoreCache?: boolean, siteId?: string) + : Promise { + return this.sitesProvider.getSite(siteId).then((site) => { const params = { courseids: [courseId], includenotenrolledcourses: 1 }, - preSets = { + preSets: CoreSiteWSPreSets = { cacheKey: this.getAssignmentCacheKey(courseId) }; + if (ignoreCache) { + preSets.getFromCache = false; + preSets.emergencyCache = false; + } + return site.read('mod_assign_get_assignments', params, preSets).catch(() => { // In 3.6 we added a new parameter includenotenrolledcourses that could cause offline data not to be found. // Retry again without the param to check if the request is already cached. @@ -172,11 +181,12 @@ export class AddonModAssignProvider { * * @param {number} courseId Course ID the assignment belongs to. * @param {number} cmId Assignment instance ID. + * @param {boolean} [ignoreCache] True if it should ignore cached data (it will always fail in offline or server down). * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved with the assignment. */ - getAssignmentById(courseId: number, id: number, siteId?: string): Promise { - return this.getAssignmentByField(courseId, 'id', id, siteId); + getAssignmentById(courseId: number, id: number, ignoreCache?: boolean, siteId?: string): Promise { + return this.getAssignmentByField(courseId, 'id', id, ignoreCache, siteId); } /** @@ -194,18 +204,24 @@ export class AddonModAssignProvider { * * @param {number} assignId Assignment Id. * @param {number} userId User Id to be blinded. + * @param {boolean} [ignoreCache] True if it should ignore cached data (it will always fail in offline or server down). * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved with the user blind id. */ - getAssignmentUserMappings(assignId: number, userId: number, siteId?: string): Promise { + getAssignmentUserMappings(assignId: number, userId: number, ignoreCache?: boolean, siteId?: string): Promise { return this.sitesProvider.getSite(siteId).then((site) => { const params = { assignmentids: [assignId] }, - preSets = { + preSets: CoreSiteWSPreSets = { cacheKey: this.getAssignmentUserMappingsCacheKey(assignId) }; + if (ignoreCache) { + preSets.getFromCache = false; + preSets.emergencyCache = false; + } + return site.read('mod_assign_get_user_mappings', params, preSets).then((response) => { // Search the user. if (response.assignments && response.assignments.length) { @@ -248,18 +264,24 @@ export class AddonModAssignProvider { * Returns grade information from assign_grades for the requested assignment id * * @param {number} assignId Assignment Id. + * @param {boolean} [ignoreCache] True if it should ignore cached data (it will always fail in offline or server down). * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Resolved with requested info when done. */ - getAssignmentGrades(assignId: number, siteId?: string): Promise { + getAssignmentGrades(assignId: number, ignoreCache?: boolean, siteId?: string): Promise { return this.sitesProvider.getSite(siteId).then((site) => { const params = { assignmentids: [assignId] }, - preSets = { + preSets: CoreSiteWSPreSets = { cacheKey: this.getAssignmentGradesCacheKey(assignId) }; + if (ignoreCache) { + preSets.getFromCache = false; + preSets.emergencyCache = false; + } + return site.read('mod_assign_get_grades', params, preSets).then((response) => { // Search the assignment. if (response.assignments && response.assignments.length) { @@ -419,18 +441,26 @@ export class AddonModAssignProvider { * Get an assignment submissions. * * @param {number} assignId Assignment id. + * @param {boolean} [ignoreCache] True if it should ignore cached data (it will always fail in offline or server down). * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise<{canviewsubmissions: boolean, submissions?: any[]}>} Promise resolved when done. */ - getSubmissions(assignId: number, siteId?: string): Promise<{canviewsubmissions: boolean, submissions?: any[]}> { + getSubmissions(assignId: number, ignoreCache?: boolean, siteId?: string) + : Promise<{canviewsubmissions: boolean, submissions?: any[]}> { + return this.sitesProvider.getSite(siteId).then((site) => { const params = { assignmentids: [assignId] }, - preSets = { + preSets: CoreSiteWSPreSets = { cacheKey: this.getSubmissionsCacheKey(assignId) }; + if (ignoreCache) { + preSets.getFromCache = false; + preSets.emergencyCache = false; + } + return site.read('mod_assign_get_submissions', params, preSets).then((response): any => { // Check if we can view submissions, with enough permissions. if (response.warnings.length > 0 && response.warnings[0].warningcode == 1) { @@ -523,7 +553,10 @@ export class AddonModAssignProvider { if (!userSubmission) { // Try again, ignoring cache. - return this.getSubmissionStatus(assign.id, userId, isBlind, filter, true, siteId); + return this.getSubmissionStatus(assign.id, userId, isBlind, filter, true, siteId).catch(() => { + // Error, return the first result even if it doesn't have the user submission. + return response; + }); } return response; @@ -578,11 +611,12 @@ export class AddonModAssignProvider { * @param {number} assignId ID of the assignment the submissions belong to. * @param {boolean} [blind] Whether the user data need to be blinded. * @param {any[]} [participants] List of participants in the assignment. + * @param {boolean} [ignoreCache] True if it should ignore cached data (it will always fail in offline or server down). * @param {string} [siteId] Site id (empty for current site). * @return {Promise} Promise always resolved. Resolve param is the formatted submissions. */ getSubmissionsUserData(submissions: any[], courseId: number, assignId: number, blind?: boolean, participants?: any[], - siteId?: string): Promise { + ignoreCache?: boolean, siteId?: string): Promise { const promises = [], subs = [], @@ -619,7 +653,7 @@ export class AddonModAssignProvider { // Blind but not blinded! (Moodle < 3.1.1, 3.2). delete submission.userid; - promise = this.getAssignmentUserMappings(assignId, submission.submitid, siteId).then((blindId) => { + promise = this.getAssignmentUserMappings(assignId, submission.submitid, ignoreCache, siteId).then((blindId) => { submission.blindid = blindId; }); } else if (!participant) { @@ -702,10 +736,11 @@ export class AddonModAssignProvider { * * @param {number} assignId Assignment id. * @param {number} [groupId] Group id. If not defined, 0. + * @param {boolean} [ignoreCache] True if it should ignore cached data (it will always fail in offline or server down). * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved with the list of participants and summary of submissions. */ - listParticipants(assignId: number, groupId?: number, siteId?: string): Promise { + listParticipants(assignId: number, groupId?: number, ignoreCache?: boolean, siteId?: string): Promise { groupId = groupId || 0; return this.sitesProvider.getSite(siteId).then((site) => { @@ -719,10 +754,15 @@ export class AddonModAssignProvider { groupid: groupId, filter: '' }, - preSets = { + preSets: CoreSiteWSPreSets = { cacheKey: this.listParticipantsCacheKey(assignId, groupId) }; + if (ignoreCache) { + preSets.getFromCache = false; + preSets.emergencyCache = false; + } + return site.read('mod_assign_list_participants', params, preSets); }); } @@ -812,7 +852,7 @@ export class AddonModAssignProvider { invalidateContent(moduleId: number, courseId: number, siteId?: string): Promise { siteId = siteId || this.sitesProvider.getCurrentSiteId(); - return this.getAssignment(courseId, moduleId, siteId).then((assign) => { + return this.getAssignment(courseId, moduleId, false, siteId).then((assign) => { const promises = []; // Do not invalidate assignment data before getting assignment info, we need it! diff --git a/src/addon/mod/assign/providers/helper.ts b/src/addon/mod/assign/providers/helper.ts index d227634de..78478936d 100644 --- a/src/addon/mod/assign/providers/helper.ts +++ b/src/addon/mod/assign/providers/helper.ts @@ -150,14 +150,15 @@ export class AddonModAssignHelperProvider { * List the participants for a single assignment, with some summary info about their submissions. * * @param {any} assign Assignment object + * @param {boolean} [ignoreCache] True if it should ignore cached data (it will always fail in offline or server down). * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise { + getParticipants(assign: any, ignoreCache?: boolean, siteId?: string): Promise { siteId = siteId || this.sitesProvider.getCurrentSiteId(); // Get the participants without specifying a group. - return this.assignProvider.listParticipants(assign.id, undefined, siteId).then((participants) => { + return this.assignProvider.listParticipants(assign.id, undefined, ignoreCache, siteId).then((participants) => { if (participants && participants.length > 0) { return participants; } @@ -168,7 +169,8 @@ export class AddonModAssignHelperProvider { participants = {}; userGroups.forEach((userGroup) => { - promises.push(this.assignProvider.listParticipants(assign.id, userGroup.id, siteId).then((parts) => { + promises.push(this.assignProvider.listParticipants(assign.id, userGroup.id, ignoreCache, siteId) + .then((parts) => { // Do not get repeated users. parts.forEach((participant) => { participants[participant.id] = participant; diff --git a/src/addon/mod/assign/providers/prefetch-handler.ts b/src/addon/mod/assign/providers/prefetch-handler.ts index a83d6c240..16f91940f 100644 --- a/src/addon/mod/assign/providers/prefetch-handler.ts +++ b/src/addon/mod/assign/providers/prefetch-handler.ts @@ -92,19 +92,19 @@ export class AddonModAssignPrefetchHandler extends CoreCourseActivityPrefetchHan siteId = siteId || this.sitesProvider.getCurrentSiteId(); - return this.assignProvider.getAssignment(courseId, module.id, siteId).then((assign) => { + return this.assignProvider.getAssignment(courseId, module.id, false, siteId).then((assign) => { // Get intro files and attachments. let files = assign.introattachments || []; files = files.concat(this.getIntroFilesFromInstance(module, assign)); // Now get the files in the submissions. - return this.assignProvider.getSubmissions(assign.id, siteId).then((data) => { + return this.assignProvider.getSubmissions(assign.id, false, siteId).then((data) => { const blindMarking = assign.blindmarking && !assign.revealidentities; if (data.canviewsubmissions) { // Teacher, get all submissions. return this.assignProvider.getSubmissionsUserData(data.submissions, courseId, assign.id, blindMarking, - undefined, siteId).then((submissions) => { + undefined, false, siteId).then((submissions) => { const promises = []; @@ -156,7 +156,7 @@ export class AddonModAssignPrefetchHandler extends CoreCourseActivityPrefetchHan protected getSubmissionFiles(assign: any, submitId: number, blindMarking: boolean, siteId?: string) : Promise { - return this.assignProvider.getSubmissionStatusWithRetry(assign, submitId, blindMarking, true, true, siteId) + return this.assignProvider.getSubmissionStatusWithRetry(assign, submitId, blindMarking, true, false, siteId) .then((response) => { const promises = []; @@ -250,12 +250,12 @@ export class AddonModAssignPrefetchHandler extends CoreCourseActivityPrefetchHan siteId = siteId || this.sitesProvider.getCurrentSiteId(); // Get assignment to retrieve all its submissions. - promises.push(this.assignProvider.getAssignment(courseId, module.id, siteId).then((assign) => { + promises.push(this.assignProvider.getAssignment(courseId, module.id, true, siteId).then((assign) => { const subPromises = [], blindMarking = assign.blindmarking && !assign.revealidentities; if (blindMarking) { - subPromises.push(this.assignProvider.getAssignmentUserMappings(assign.id, undefined, siteId).catch(() => { + subPromises.push(this.assignProvider.getAssignmentUserMappings(assign.id, undefined, true, siteId).catch(() => { // Ignore errors. })); } @@ -289,14 +289,14 @@ export class AddonModAssignPrefetchHandler extends CoreCourseActivityPrefetchHan protected prefetchSubmissions(assign: any, courseId: number, moduleId: number, userId: number, siteId: string): Promise { // Get submissions. - return this.assignProvider.getSubmissions(assign.id, siteId).then((data) => { + return this.assignProvider.getSubmissions(assign.id, true, siteId).then((data) => { const promises = [], blindMarking = assign.blindmarking && !assign.revealidentities; if (data.canviewsubmissions) { // Teacher. Do not send participants to getSubmissionsUserData to retrieve user profiles. promises.push(this.assignProvider.getSubmissionsUserData(data.submissions, courseId, assign.id, blindMarking, - undefined, siteId).then((submissions) => { + undefined, true, siteId).then((submissions) => { const subPromises = []; @@ -316,7 +316,7 @@ export class AddonModAssignPrefetchHandler extends CoreCourseActivityPrefetchHan if (!assign.markingworkflow) { // Get assignment grades only if workflow is not enabled to check grading date. - subPromises.push(this.assignProvider.getAssignmentGrades(assign.id, siteId)); + subPromises.push(this.assignProvider.getAssignmentGrades(assign.id, true, siteId)); } // Prefetch the submission of the current user even if it does not exist, this will be create it. @@ -331,7 +331,7 @@ export class AddonModAssignPrefetchHandler extends CoreCourseActivityPrefetchHan })); // Get list participants. - promises.push(this.assignHelper.getParticipants(assign, siteId).then((participants) => { + promises.push(this.assignHelper.getParticipants(assign, true, siteId).then((participants) => { participants.forEach((participant) => { if (participant.profileimageurl) { this.filepoolProvider.addToQueueByUrl(siteId, participant.profileimageurl); @@ -354,8 +354,8 @@ export class AddonModAssignPrefetchHandler extends CoreCourseActivityPrefetchHan ); } - promises.push(this.groupsProvider.activityHasGroups(assign.cmid)); - promises.push(this.groupsProvider.getActivityAllowedGroups(assign.cmid, undefined, siteId)); + promises.push(this.groupsProvider.activityHasGroups(assign.cmid, siteId, true)); + promises.push(this.groupsProvider.getActivityAllowedGroups(assign.cmid, undefined, siteId, true)); return Promise.all(promises); }); @@ -419,7 +419,7 @@ export class AddonModAssignPrefetchHandler extends CoreCourseActivityPrefetchHan } if (userId) { - promises.push(this.gradesHelper.getGradeModuleItems(courseId, moduleId, userId, undefined, siteId)); + promises.push(this.gradesHelper.getGradeModuleItems(courseId, moduleId, userId, undefined, siteId, true)); } // Prefetch feedback plugins data. diff --git a/src/providers/groups.ts b/src/providers/groups.ts index 8afc57ee6..437e6e03f 100644 --- a/src/providers/groups.ts +++ b/src/providers/groups.ts @@ -16,6 +16,7 @@ import { Injectable } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { CoreSitesProvider } from './sites'; import { CoreCoursesProvider } from '@core/courses/providers/courses'; +import { CoreSiteWSPreSets } from '@classes/site'; /** * Group info for an activity. @@ -59,10 +60,11 @@ export class CoreGroupsProvider { * * @param {number} cmId Course module ID. * @param {string} [siteId] Site ID. If not defined, current site. + * @param {boolean} [ignoreCache] True if it should ignore cached data (it will always fail in offline or server down). * @return {Promise} Promise resolved with true if the activity has groups, resolved with false otherwise. */ - activityHasGroups(cmId: number, siteId?: string): Promise { - return this.getActivityGroupMode(cmId, siteId).then((groupmode) => { + activityHasGroups(cmId: number, siteId?: string, ignoreCache?: boolean): Promise { + return this.getActivityGroupMode(cmId, siteId, ignoreCache).then((groupmode) => { return groupmode === CoreGroupsProvider.SEPARATEGROUPS || groupmode === CoreGroupsProvider.VISIBLEGROUPS; }).catch(() => { return false; @@ -75,9 +77,10 @@ export class CoreGroupsProvider { * @param {number} cmId Course module ID. * @param {number} [userId] User ID. If not defined, use current user. * @param {string} [siteId] Site ID. If not defined, current site. + * @param {boolean} [ignoreCache] True if it should ignore cached data (it will always fail in offline or server down). * @return {Promise} Promise resolved when the groups are retrieved. */ - getActivityAllowedGroups(cmId: number, userId?: number, siteId?: string): Promise { + getActivityAllowedGroups(cmId: number, userId?: number, siteId?: string, ignoreCache?: boolean): Promise { return this.sitesProvider.getSite(siteId).then((site) => { userId = userId || site.getUserId(); @@ -85,10 +88,15 @@ export class CoreGroupsProvider { cmid: cmId, userid: userId }, - preSets = { + preSets: CoreSiteWSPreSets = { cacheKey: this.getActivityAllowedGroupsCacheKey(cmId, userId) }; + if (ignoreCache) { + preSets.getFromCache = false; + preSets.emergencyCache = false; + } + return site.read('core_group_get_activity_allowed_groups', params, preSets).then((response) => { if (!response || !response.groups) { return Promise.reject(null); @@ -175,17 +183,23 @@ export class CoreGroupsProvider { * * @param {number} cmId Course module ID. * @param {string} [siteId] Site ID. If not defined, current site. + * @param {boolean} [ignoreCache] True if it should ignore cached data (it will always fail in offline or server down). * @return {Promise} Promise resolved when the group mode is retrieved. */ - getActivityGroupMode(cmId: number, siteId?: string): Promise { + getActivityGroupMode(cmId: number, siteId?: string, ignoreCache?: boolean): Promise { return this.sitesProvider.getSite(siteId).then((site) => { const params = { cmid: cmId }, - preSets = { + preSets: CoreSiteWSPreSets = { cacheKey: this.getActivityGroupModeCacheKey(cmId) }; + if (ignoreCache) { + preSets.getFromCache = false; + preSets.emergencyCache = false; + } + return site.read('core_group_get_activity_groupmode', params, preSets).then((response) => { if (!response || typeof response.groupmode == 'undefined') { return Promise.reject(null);