Merge pull request #3327 from dpalou/MOBILE-4099
MOBILE-4099 scorm: Don't call WS if user cannot save tracks
This commit is contained in:
		
						commit
						82918f787b
					
				| @ -93,13 +93,6 @@ export class AddonModScormDataModel12 { | |||||||
|     protected errorCode = '0'; // Last error.
 |     protected errorCode = '0'; // Last error.
 | ||||||
|     protected timeout?: number; // Timeout to commit changes.
 |     protected timeout?: number; // Timeout to commit changes.
 | ||||||
| 
 | 
 | ||||||
|     protected siteId: string; |  | ||||||
|     protected scorm: AddonModScormScorm; |  | ||||||
|     protected scoId: number; |  | ||||||
|     protected attempt: number; |  | ||||||
|     protected mode: string; |  | ||||||
|     protected offline: boolean; |  | ||||||
| 
 |  | ||||||
|     /** |     /** | ||||||
|      * Constructor. |      * Constructor. | ||||||
|      * |      * | ||||||
| @ -110,23 +103,18 @@ export class AddonModScormDataModel12 { | |||||||
|      * @param userData The user default data. |      * @param userData The user default data. | ||||||
|      * @param mode Mode being played. By default, MODENORMAL. |      * @param mode Mode being played. By default, MODENORMAL. | ||||||
|      * @param offline Whether the attempt is offline. |      * @param offline Whether the attempt is offline. | ||||||
|  |      * @param canSaveTracks Whether the user can save tracks. | ||||||
|      */ |      */ | ||||||
|     constructor( |     constructor( | ||||||
|         siteId: string, |         protected siteId: string, | ||||||
|         scorm: AddonModScormScorm, |         protected scorm: AddonModScormScorm, | ||||||
|         scoId: number, |         protected scoId: number, | ||||||
|         attempt: number, |         protected attempt: number, | ||||||
|         userData: AddonModScormUserDataMap, |         protected userData: AddonModScormUserDataMap, | ||||||
|         mode?: string, |         protected mode = AddonModScormProvider.MODENORMAL, | ||||||
|         offline?: boolean, |         protected offline = false, | ||||||
|  |         protected canSaveTracks = true, | ||||||
|     ) { |     ) { | ||||||
|         this.siteId = siteId; |  | ||||||
|         this.scorm = scorm; |  | ||||||
|         this.scoId = scoId; |  | ||||||
|         this.attempt = attempt; |  | ||||||
|         this.mode = mode || AddonModScormProvider.MODENORMAL; |  | ||||||
|         this.offline = !!offline; |  | ||||||
| 
 |  | ||||||
|         this.init(userData); |         this.init(userData); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -522,8 +510,9 @@ export class AddonModScormDataModel12 { | |||||||
|             // Load default values.
 |             // Load default values.
 | ||||||
|             for (const element in this.dataModel[scoId]) { |             for (const element in this.dataModel[scoId]) { | ||||||
|                 if (element.match(/\.n\./) === null) { |                 if (element.match(/\.n\./) === null) { | ||||||
|                     if (this.dataModel[scoId][element].defaultvalue !== undefined) { |                     const defaultValue = this.dataModel[scoId][element].defaultvalue; | ||||||
|                         this.currentUserData[scoId].userdata[element] = this.dataModel[scoId][element].defaultvalue!; |                     if (defaultValue !== undefined) { | ||||||
|  |                         this.currentUserData[scoId].userdata[element] = defaultValue; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| @ -531,8 +520,9 @@ export class AddonModScormDataModel12 { | |||||||
|             // Load initial user data for current SCO.
 |             // Load initial user data for current SCO.
 | ||||||
|             for (const element in this.def[scoId]) { |             for (const element in this.def[scoId]) { | ||||||
|                 if (element.match(/\.n\./) === null) { |                 if (element.match(/\.n\./) === null) { | ||||||
|                     if (this.dataModel[scoId][element].defaultvalue !== undefined) { |                     const defaultValue = this.dataModel[scoId][element].defaultvalue; | ||||||
|                         this.currentUserData[scoId].userdata[element] = this.dataModel[scoId][element].defaultvalue!; |                     if (defaultValue !== undefined) { | ||||||
|  |                         this.currentUserData[scoId].userdata[element] = defaultValue; | ||||||
|                     } else if (this.defExtra[scoId][element] !== undefined) { |                     } else if (this.defExtra[scoId][element] !== undefined) { | ||||||
|                         // Check in user data values.
 |                         // Check in user data values.
 | ||||||
|                         this.currentUserData[scoId].userdata[element] = this.defExtra[scoId][element]; |                         this.currentUserData[scoId].userdata[element] = this.defExtra[scoId][element]; | ||||||
| @ -820,7 +810,7 @@ export class AddonModScormDataModel12 { | |||||||
| 
 | 
 | ||||||
|                 if (this.dataModel[this.scoId][elementModel] !== undefined) { |                 if (this.dataModel[this.scoId][elementModel] !== undefined) { | ||||||
|                     if (this.dataModel[this.scoId][elementModel].mod != 'r') { |                     if (this.dataModel[this.scoId][elementModel].mod != 'r') { | ||||||
|                         expression = new RegExp(this.dataModel[this.scoId][elementModel].format!); |                         expression = new RegExp(this.dataModel[this.scoId][elementModel].format ?? ''); | ||||||
|                         value = value + ''; |                         value = value + ''; | ||||||
| 
 | 
 | ||||||
|                         const matches = value.match(expression); |                         const matches = value.match(expression); | ||||||
| @ -981,6 +971,10 @@ export class AddonModScormDataModel12 { | |||||||
|      * @return True if success, false otherwise. |      * @return True if success, false otherwise. | ||||||
|      */ |      */ | ||||||
|     protected storeData(storeTotalTime?: boolean): boolean { |     protected storeData(storeTotalTime?: boolean): boolean { | ||||||
|  |         if (!this.canSaveTracks) { | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         let tracks: AddonModScormDataEntry[]; |         let tracks: AddonModScormDataEntry[]; | ||||||
| 
 | 
 | ||||||
|         if (storeTotalTime) { |         if (storeTotalTime) { | ||||||
|  | |||||||
| @ -132,6 +132,10 @@ export class AddonModScormPlayerPage implements OnInit, OnDestroy { | |||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     get canSaveTracks(): boolean { | ||||||
|  |         return !this.accessInfo || !!this.accessInfo.cansavetrack; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /** |     /** | ||||||
|      * Initialize. |      * Initialize. | ||||||
|      * |      * | ||||||
| @ -235,9 +239,13 @@ export class AddonModScormPlayerPage implements OnInit, OnDestroy { | |||||||
|      * Determine the attempt to use, the mode (normal/preview) and if it's offline or online. |      * Determine the attempt to use, the mode (normal/preview) and if it's offline or online. | ||||||
|      * |      * | ||||||
|      * @param attemptsData Attempts count. |      * @param attemptsData Attempts count. | ||||||
|  |      * @param accessInfo Access info. | ||||||
|      * @return Promise resolved when done. |      * @return Promise resolved when done. | ||||||
|      */ |      */ | ||||||
|     protected async determineAttemptAndMode(attemptsData: AddonModScormAttemptCountResult): Promise<void> { |     protected async determineAttemptAndMode( | ||||||
|  |         attemptsData: AddonModScormAttemptCountResult, | ||||||
|  |         accessInfo: AddonModScormGetScormAccessInformationWSResponse, | ||||||
|  |     ): Promise<void> { | ||||||
|         const data = await AddonModScormHelper.determineAttemptToContinue(this.scorm, attemptsData); |         const data = await AddonModScormHelper.determineAttemptToContinue(this.scorm, attemptsData); | ||||||
| 
 | 
 | ||||||
|         let incomplete = false; |         let incomplete = false; | ||||||
| @ -257,7 +265,14 @@ export class AddonModScormPlayerPage implements OnInit, OnDestroy { | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // Determine mode and attempt to use.
 |         // Determine mode and attempt to use.
 | ||||||
|         const result = AddonModScorm.determineAttemptAndMode(this.scorm, this.mode, this.attempt, this.newAttempt, incomplete); |         const result = AddonModScorm.determineAttemptAndMode( | ||||||
|  |             this.scorm, | ||||||
|  |             this.mode, | ||||||
|  |             this.attempt, | ||||||
|  |             this.newAttempt, | ||||||
|  |             incomplete, | ||||||
|  |             accessInfo.cansavetrack, | ||||||
|  |         ); | ||||||
| 
 | 
 | ||||||
|         if (result.attempt > this.attempt) { |         if (result.attempt > this.attempt) { | ||||||
|             // We're creating a new attempt.
 |             // We're creating a new attempt.
 | ||||||
| @ -300,23 +315,26 @@ export class AddonModScormPlayerPage implements OnInit, OnDestroy { | |||||||
| 
 | 
 | ||||||
|         try { |         try { | ||||||
|             // Get attempts data.
 |             // Get attempts data.
 | ||||||
|             const attemptsData = await AddonModScorm.getAttemptCount(this.scorm.id, { cmId: this.cmId }); |             const [attemptsData, accessInfo] = await Promise.all([ | ||||||
|  |                 AddonModScorm.getAttemptCount(this.scorm.id, { cmId: this.cmId }), | ||||||
|  |                 AddonModScorm.getAccessInformation(this.scorm.id, { | ||||||
|  |                     cmId: this.cmId, | ||||||
|  |                 }), | ||||||
|  |             ]); | ||||||
| 
 | 
 | ||||||
|             await this.determineAttemptAndMode(attemptsData); |             this.accessInfo = accessInfo; | ||||||
| 
 | 
 | ||||||
|             const [data, accessInfo] = await Promise.all([ |             await this.determineAttemptAndMode(attemptsData, accessInfo); | ||||||
|  | 
 | ||||||
|  |             const [data] = await Promise.all([ | ||||||
|                 AddonModScorm.getScormUserData(this.scorm.id, this.attempt, { |                 AddonModScorm.getScormUserData(this.scorm.id, this.attempt, { | ||||||
|                     cmId: this.cmId, |                     cmId: this.cmId, | ||||||
|                     offline: this.offline, |                     offline: this.offline, | ||||||
|                 }), |                 }), | ||||||
|                 AddonModScorm.getAccessInformation(this.scorm.id, { |  | ||||||
|                     cmId: this.cmId, |  | ||||||
|                 }), |  | ||||||
|                 this.fetchToc(), |                 this.fetchToc(), | ||||||
|             ]); |             ]); | ||||||
| 
 | 
 | ||||||
|             this.userData = data; |             this.userData = data; | ||||||
|             this.accessInfo = accessInfo; |  | ||||||
|         } catch (error) { |         } catch (error) { | ||||||
|             CoreDomUtils.showErrorModalDefault(error, 'addon.mod_scorm.errorgetscorm', true); |             CoreDomUtils.showErrorModalDefault(error, 'addon.mod_scorm.errorgetscorm', true); | ||||||
|         } |         } | ||||||
| @ -397,9 +415,10 @@ export class AddonModScormPlayerPage implements OnInit, OnDestroy { | |||||||
|                 this.scorm, |                 this.scorm, | ||||||
|                 sco.id, |                 sco.id, | ||||||
|                 this.attempt, |                 this.attempt, | ||||||
|                 this.userData!, |                 this.userData ?? {}, | ||||||
|                 this.mode, |                 this.mode, | ||||||
|                 this.offline, |                 this.offline, | ||||||
|  |                 this.canSaveTracks, | ||||||
|             ); |             ); | ||||||
| 
 | 
 | ||||||
|             // Add the model to the window so the SCORM can access it.
 |             // Add the model to the window so the SCORM can access it.
 | ||||||
| @ -453,6 +472,10 @@ export class AddonModScormPlayerPage implements OnInit, OnDestroy { | |||||||
|      * @return Promise resolved when done. |      * @return Promise resolved when done. | ||||||
|      */ |      */ | ||||||
|     protected async markCompleted(sco: AddonModScormScoWithData): Promise<void> { |     protected async markCompleted(sco: AddonModScormScoWithData): Promise<void> { | ||||||
|  |         if (!this.canSaveTracks) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         const tracks = [{ |         const tracks = [{ | ||||||
|             element: 'cmi.core.lesson_status', |             element: 'cmi.core.lesson_status', | ||||||
|             value: 'completed', |             value: 'completed', | ||||||
| @ -536,6 +559,10 @@ export class AddonModScormPlayerPage implements OnInit, OnDestroy { | |||||||
|      * @return Promise resolved when done. |      * @return Promise resolved when done. | ||||||
|      */ |      */ | ||||||
|     protected async setStartTime(scoId: number): Promise<void> { |     protected async setStartTime(scoId: number): Promise<void> { | ||||||
|  |         if (!this.canSaveTracks) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         const tracks = [{ |         const tracks = [{ | ||||||
|             element: 'x.start.time', |             element: 'x.start.time', | ||||||
|             value: String(CoreTimeUtils.timestamp()), |             value: String(CoreTimeUtils.timestamp()), | ||||||
|  | |||||||
| @ -89,7 +89,7 @@ export class AddonModScormPrefetchHandlerService extends CoreCourseActivityPrefe | |||||||
|         ]); |         ]); | ||||||
| 
 | 
 | ||||||
|         // Success, return the hash.
 |         // Success, return the hash.
 | ||||||
|         return scorm.sha1hash!; |         return scorm.sha1hash ?? ''; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
| @ -112,7 +112,7 @@ export class AddonModScormPrefetchHandlerService extends CoreCourseActivityPrefe | |||||||
|         const packageUrl = AddonModScorm.getPackageUrl(scorm); |         const packageUrl = AddonModScorm.getPackageUrl(scorm); | ||||||
| 
 | 
 | ||||||
|         // Get the folder where the unzipped files will be.
 |         // Get the folder where the unzipped files will be.
 | ||||||
|         const dirPath = await AddonModScorm.getScormFolder(scorm.moduleurl!); |         const dirPath = await AddonModScorm.getScormFolder(scorm.moduleurl ?? ''); | ||||||
| 
 | 
 | ||||||
|         // Notify that the download is starting.
 |         // Notify that the download is starting.
 | ||||||
|         onProgress && onProgress({ message: 'core.downloading' }); |         onProgress && onProgress({ message: 'core.downloading' }); | ||||||
| @ -282,7 +282,7 @@ export class AddonModScormPrefetchHandlerService extends CoreCourseActivityPrefe | |||||||
|         const scorm = await this.getScorm(module, courseId); |         const scorm = await this.getScorm(module, courseId); | ||||||
| 
 | 
 | ||||||
|         // Get the folder where SCORM should be unzipped.
 |         // Get the folder where SCORM should be unzipped.
 | ||||||
|         const path = await AddonModScorm.getScormFolder(scorm.moduleurl!); |         const path = await AddonModScorm.getScormFolder(scorm.moduleurl ?? ''); | ||||||
| 
 | 
 | ||||||
|         return CoreFile.getDirectorySize(path); |         return CoreFile.getDirectorySize(path); | ||||||
|     } |     } | ||||||
| @ -388,7 +388,7 @@ export class AddonModScormPrefetchHandlerService extends CoreCourseActivityPrefe | |||||||
|         const scorm = await this.getScorm(module, courseId, siteId); |         const scorm = await this.getScorm(module, courseId, siteId); | ||||||
| 
 | 
 | ||||||
|         // Get the folder where SCORM should be unzipped.
 |         // Get the folder where SCORM should be unzipped.
 | ||||||
|         const path = await AddonModScorm.getScormFolder(scorm.moduleurl!); |         const path = await AddonModScorm.getScormFolder(scorm.moduleurl ?? ''); | ||||||
| 
 | 
 | ||||||
|         const promises: Promise<unknown>[] = []; |         const promises: Promise<unknown>[] = []; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -484,7 +484,7 @@ export class AddonModScormOfflineProvider { | |||||||
|                 response[scoId] = { |                 response[scoId] = { | ||||||
|                     scoid: scoId, |                     scoid: scoId, | ||||||
|                     userdata: { |                     userdata: { | ||||||
|                         userid: userId!, |                         userid: userId ?? site.getUserId(), | ||||||
|                         scoid: scoId, |                         scoid: scoId, | ||||||
|                         timemodified: 0, |                         timemodified: 0, | ||||||
|                     }, |                     }, | ||||||
| @ -492,7 +492,7 @@ export class AddonModScormOfflineProvider { | |||||||
|                 }; |                 }; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             response[scoId].userdata[entry.element] = entry.value!; |             response[scoId].userdata[entry.element] = entry.value ?? ''; | ||||||
|             if (entry.timemodified > Number(response[scoId].userdata.timemodified)) { |             if (entry.timemodified > Number(response[scoId].userdata.timemodified)) { | ||||||
|                 response[scoId].userdata.timemodified = entry.timemodified; |                 response[scoId].userdata.timemodified = entry.timemodified; | ||||||
|             } |             } | ||||||
|  | |||||||
| @ -777,7 +777,7 @@ export class AddonModScormSyncProvider extends CoreCourseActivitySyncBaseProvide | |||||||
|                         lastOffline, |                         lastOffline, | ||||||
|                         newAttemptsSameOrder, |                         newAttemptsSameOrder, | ||||||
|                         newAttemptsAtEnd, |                         newAttemptsAtEnd, | ||||||
|                         lastOfflineData.timecreated!, |                         lastOfflineData.timecreated ?? 0, | ||||||
|                         lastOfflineData.incomplete, |                         lastOfflineData.incomplete, | ||||||
|                         warnings, |                         warnings, | ||||||
|                         siteId, |                         siteId, | ||||||
| @ -812,7 +812,7 @@ export class AddonModScormSyncProvider extends CoreCourseActivitySyncBaseProvide | |||||||
|                         lastOffline, |                         lastOffline, | ||||||
|                         newAttemptsSameOrder, |                         newAttemptsSameOrder, | ||||||
|                         newAttemptsAtEnd, |                         newAttemptsAtEnd, | ||||||
|                         lastOfflineData.timecreated!, |                         lastOfflineData.timecreated ?? 0, | ||||||
|                         lastOfflineData.incomplete, |                         lastOfflineData.incomplete, | ||||||
|                         warnings, |                         warnings, | ||||||
|                         siteId, |                         siteId, | ||||||
|  | |||||||
| @ -206,6 +206,7 @@ export class AddonModScormProvider { | |||||||
|      * @param attempt Current attempt. |      * @param attempt Current attempt. | ||||||
|      * @param newAttempt Whether it should start a new attempt. |      * @param newAttempt Whether it should start a new attempt. | ||||||
|      * @param incomplete Whether current attempt is incomplete. |      * @param incomplete Whether current attempt is incomplete. | ||||||
|  |      * @param canSaveTracks Whether the user can save tracks. | ||||||
|      * @return Mode, attempt number and whether to start a new attempt. |      * @return Mode, attempt number and whether to start a new attempt. | ||||||
|      */ |      */ | ||||||
|     determineAttemptAndMode( |     determineAttemptAndMode( | ||||||
| @ -214,7 +215,15 @@ export class AddonModScormProvider { | |||||||
|         attempt: number, |         attempt: number, | ||||||
|         newAttempt?: boolean, |         newAttempt?: boolean, | ||||||
|         incomplete?: boolean, |         incomplete?: boolean, | ||||||
|  |         canSaveTracks = true, | ||||||
|     ): {mode: string; attempt: number; newAttempt: boolean} { |     ): {mode: string; attempt: number; newAttempt: boolean} { | ||||||
|  |         if (!canSaveTracks) { | ||||||
|  |             return { | ||||||
|  |                 mode: scorm.hidebrowse ? AddonModScormProvider.MODENORMAL : mode, | ||||||
|  |                 attempt, | ||||||
|  |                 newAttempt: false, | ||||||
|  |             }; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         if (mode == AddonModScormProvider.MODEBROWSE) { |         if (mode == AddonModScormProvider.MODEBROWSE) { | ||||||
|             if (scorm.hidebrowse) { |             if (scorm.hidebrowse) { | ||||||
| @ -348,8 +357,8 @@ export class AddonModScormProvider { | |||||||
|                     element = '!'; |                     element = '!'; | ||||||
|                 } else if (reOther.test(element)) { |                 } else if (reOther.test(element)) { | ||||||
|                     // Other symbols = | <> .
 |                     // Other symbols = | <> .
 | ||||||
|                     matches = element.match(reOther)!; |                     matches = element.match(reOther) ?? []; | ||||||
|                     element = matches[1].trim(); |                     element = matches[1]?.trim(); | ||||||
| 
 | 
 | ||||||
|                     if (trackData[element] !== undefined) { |                     if (trackData[element] !== undefined) { | ||||||
|                         let value = matches[3].trim().replace(/('|")/gi, ''); |                         let value = matches[3].trim().replace(/('|")/gi, ''); | ||||||
| @ -959,7 +968,7 @@ export class AddonModScormProvider { | |||||||
|             return launchUrl; |             return launchUrl; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         const dirPath = await CoreFilepool.getPackageDirUrlByUrl(siteId, scorm.moduleurl!); |         const dirPath = await CoreFilepool.getPackageDirUrlByUrl(siteId, scorm.moduleurl ?? ''); | ||||||
| 
 | 
 | ||||||
|         return CoreText.concatenatePaths(dirPath, launchUrl); |         return CoreText.concatenatePaths(dirPath, launchUrl); | ||||||
|     } |     } | ||||||
| @ -1564,7 +1573,7 @@ export class AddonModScormProvider { | |||||||
|         userData?: AddonModScormUserDataMap, |         userData?: AddonModScormUserDataMap, | ||||||
|     ): boolean { |     ): boolean { | ||||||
|         if (offline) { |         if (offline) { | ||||||
|             return AddonModScormOffline.saveTracksSync(scorm, scoId, attempt, tracks, userData!); |             return AddonModScormOffline.saveTracksSync(scorm, scoId, attempt, tracks, userData ?? {}); | ||||||
|         } else { |         } else { | ||||||
|             const success = this.saveTracksSyncOnline(scoId, attempt, tracks); |             const success = this.saveTracksSyncOnline(scoId, attempt, tracks); | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user