Merge pull request #3327 from dpalou/MOBILE-4099
MOBILE-4099 scorm: Don't call WS if user cannot save tracksmain
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…
Reference in New Issue