Skip to content

Commit 7271ee3

Browse files
authored
Merge pull request #4175 from albertgasset/MOBILE-4642
MOBILE-4642 h5p: Prevent partially saved packages
2 parents 437f309 + 6624d13 commit 7271ee3

File tree

2 files changed

+49
-23
lines changed

2 files changed

+49
-23
lines changed

src/core/features/h5p/classes/file-storage.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,4 +449,43 @@ export class CoreH5PFileStorage {
449449
}
450450
}
451451

452+
/**
453+
* Check that library is fully saved to the file system.
454+
*
455+
* @param libraryData Library data.
456+
* @param siteId Site ID. If not defined, current site.
457+
* @returns Promise resolved with true if all library files are present.
458+
*/
459+
async checkLibrary(libraryData: CoreH5PLibraryBeingSaved, siteId?: string): Promise<boolean> {
460+
const getFileNames = async (baseDir: string, dirName = ''): Promise<string[]> => {
461+
const entries = await CoreFile.getDirectoryContents( baseDir + dirName);
462+
const fileNames: string[] = [];
463+
464+
for (const entry of entries) {
465+
const name = dirName + '/' + entry.name;
466+
if (entry.isDirectory) {
467+
fileNames.push(...(await getFileNames(baseDir, name)));
468+
} else {
469+
fileNames.push(name);
470+
}
471+
}
472+
473+
return fileNames;
474+
};
475+
476+
if (!libraryData.uploadDirectory) {
477+
return true;
478+
}
479+
480+
siteId = siteId || CoreSites.getCurrentSiteId();
481+
const folderPath = this.getLibraryFolderPath(libraryData, siteId);
482+
483+
const [sourceFiles, destFiles] = await Promise.all([
484+
getFileNames(libraryData.uploadDirectory),
485+
getFileNames(folderPath).catch(() => ([])).then(files => new Set(files)),
486+
]);
487+
488+
return sourceFiles.every(name => destFiles.has(name));
489+
}
490+
452491
}

src/core/features/h5p/classes/storage.ts

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,9 @@ export class CoreH5PStorage {
6565

6666
const newerPatchVersion = existingLibrary.patchversion < libraryData.patchVersion;
6767

68-
if (!newerPatchVersion) {
68+
// Make sure the library is fully saved to the file system if it is present in the DB.
69+
// Some files might be missing if a previous library update was interrupted.
70+
if (!newerPatchVersion && await this.h5pCore.h5pFS.checkLibrary(libraryData, siteId)) {
6971
// Same or older version, no need to save.
7072
libraryData.saveDependencies = false;
7173

@@ -79,21 +81,12 @@ export class CoreH5PStorage {
7981
libraryData.metadataSettings = libraryData.metadataSettings ?
8082
CoreH5PMetadata.boolifyAndEncodeSettings(libraryData.metadataSettings) : undefined;
8183

84+
// Save the library files before saving to DB, in case the app is closed while copying the files.
85+
await this.h5pCore.h5pFS.saveLibrary(libraryData, siteId);
86+
8287
// Save the library data in DB.
8388
await this.h5pFramework.saveLibraryData(libraryData, siteId);
8489

85-
// Now save it in FS.
86-
try {
87-
await this.h5pCore.h5pFS.saveLibrary(libraryData, siteId);
88-
} catch (error) {
89-
if (libraryData.libraryId) {
90-
// An error occurred, delete the DB data because the lib FS data has been deleted.
91-
await this.h5pFramework.deleteLibrary(libraryData.libraryId, siteId);
92-
}
93-
94-
throw error;
95-
}
96-
9790
if (libraryData.libraryId !== undefined) {
9891
const promises: Promise<void>[] = [];
9992

@@ -196,21 +189,15 @@ export class CoreH5PStorage {
196189

197190
content.params = JSON.stringify(data.contentJsonData);
198191

199-
// Save the content data in DB.
200-
await this.h5pCore.saveContent(content, folderName, fileUrl, siteId);
201-
202192
// Save the content files in their right place in FS.
203193
const destFolder = CorePath.concatenatePaths(CoreFileProvider.TMPFOLDER, 'h5p/' + folderName);
204194
const contentPath = CorePath.concatenatePaths(destFolder, 'content');
205195

206-
try {
207-
await this.h5pCore.h5pFS.saveContent(contentPath, folderName, siteId);
208-
} catch (error) {
209-
// An error occurred, delete the DB data because the content files have been deleted.
210-
await this.h5pFramework.deleteContentData(content.id!, siteId);
196+
// Save the content files before saving to DB, in case the app is closed while copying the files.
197+
await this.h5pCore.h5pFS.saveContent(contentPath, folderName, siteId);
211198

212-
throw error;
213-
}
199+
// Save the content data in DB.
200+
await this.h5pCore.saveContent(content, folderName, fileUrl, siteId);
214201
}
215202

216203
return content;

0 commit comments

Comments
 (0)