MOBILE-4304 h5p: Update database usage

main
Noel De Martin 2024-01-17 17:00:26 +01:00
parent 807860f0d5
commit ef88336a2d
6 changed files with 215 additions and 92 deletions

View File

@ -187,6 +187,13 @@ export class CoreDatabaseTableProxy<
return this.target.delete(conditions); return this.target.delete(conditions);
} }
/**
* @inheritdoc
*/
async deleteWhere(conditions: CoreDatabaseConditions<DBRecord>): Promise<void> {
return this.target.deleteWhere(conditions);
}
/** /**
* @inheritdoc * @inheritdoc
*/ */

View File

@ -311,6 +311,18 @@ export class CoreDatabaseTable<
: await this.database.deleteRecords(this.tableName); : await this.database.deleteRecords(this.tableName);
} }
/**
* Delete records matching the given conditions.
*
* This method should be used when it's necessary to apply complex conditions; the simple `delete`
* method should be favored otherwise for better performance.
*
* @param conditions Matching conditions in SQL and JavaScript.
*/
async deleteWhere(conditions: CoreDatabaseConditions<DBRecord>): Promise<void> {
await this.database.deleteRecordsSelect(this.tableName, conditions.sql, conditions.sqlParams);
}
/** /**
* Delete a single record identified by its primary key. * Delete a single record identified by its primary key.
* *

View File

@ -186,6 +186,15 @@ export class CoreDebugDatabaseTable<
return this.target.delete(conditions); return this.target.delete(conditions);
} }
/**
* @inheritdoc
*/
async deleteWhere(conditions: CoreDatabaseConditions<DBRecord>): Promise<void> {
this.logger.log('deleteWhere', conditions);
return this.target.deleteWhere(conditions);
}
/** /**
* @inheritdoc * @inheritdoc
*/ */

View File

@ -202,12 +202,27 @@ export class CoreEagerDatabaseTable<
return; return;
} }
Object.entries(this.records).forEach(([id, record]) => { Object.entries(this.records).forEach(([primaryKey, record]) => {
if (!this.recordMatches(record, conditions)) { if (!this.recordMatches(record, conditions)) {
return; return;
} }
delete this.records[id]; delete this.records[primaryKey];
});
}
/**
* @inheritdoc
*/
async deleteWhere(conditions: CoreDatabaseConditions<DBRecord>): Promise<void> {
await super.deleteWhere(conditions);
Object.entries(this.records).forEach(([primaryKey, record]) => {
if (!conditions.js(record)) {
return;
}
delete record[primaryKey];
}); });
} }

View File

@ -189,6 +189,21 @@ export class CoreLazyDatabaseTable<
} }
} }
/**
* @inheritdoc
*/
async deleteWhere(conditions: CoreDatabaseConditions<DBRecord>): Promise<void> {
await super.deleteWhere(conditions);
Object.entries(this.records).forEach(([primaryKey, record]) => {
if (!record || !conditions.js(record)) {
return;
}
this.records[primaryKey] = null;
});
}
/** /**
* @inheritdoc * @inheritdoc
*/ */

View File

@ -44,12 +44,85 @@ import { CoreH5PLibraryAddTo, CoreH5PLibraryMetadataSettings } from './validator
import { CoreH5PMetadata } from './metadata'; import { CoreH5PMetadata } from './metadata';
import { Translate } from '@singletons'; import { Translate } from '@singletons';
import { SQLiteDB } from '@classes/sqlitedb'; import { SQLiteDB } from '@classes/sqlitedb';
import { AsyncInstance, asyncInstance } from '@/core/utils/async-instance';
import { LazyMap, lazyMap } from '@/core/utils/lazy-map';
import { CoreDatabaseTable } from '@classes/database/database-table';
import { CoreDatabaseCachingStrategy } from '@classes/database/database-table-proxy';
/** /**
* Equivalent to Moodle's implementation of H5PFrameworkInterface. * Equivalent to Moodle's implementation of H5PFrameworkInterface.
*/ */
export class CoreH5PFramework { export class CoreH5PFramework {
protected contentTables: LazyMap<AsyncInstance<CoreDatabaseTable<CoreH5PContentDBRecord>>>;
protected librariesTables: LazyMap<AsyncInstance<CoreDatabaseTable<CoreH5PLibraryDBRecord>>>;
protected libraryDependenciesTables: LazyMap<AsyncInstance<CoreDatabaseTable<CoreH5PLibraryDependencyDBRecord>>>;
protected contentsLibrariesTables: LazyMap<AsyncInstance<CoreDatabaseTable<CoreH5PContentsLibraryDBRecord>>>;
protected librariesCachedAssetsTables: LazyMap<AsyncInstance<CoreDatabaseTable<CoreH5PLibraryCachedAssetsDBRecord>>>;
constructor() {
this.contentTables = lazyMap(
siteId => asyncInstance(
() => CoreSites.getSiteTable(
CONTENT_TABLE_NAME,
{
siteId,
config: { cachingStrategy: CoreDatabaseCachingStrategy.None },
onDestroy: () => delete this.contentTables[siteId],
},
),
),
);
this.librariesTables = lazyMap(
siteId => asyncInstance(
() => CoreSites.getSiteTable(
LIBRARIES_TABLE_NAME,
{
siteId,
config: { cachingStrategy: CoreDatabaseCachingStrategy.None },
onDestroy: () => delete this.librariesTables[siteId],
},
),
),
);
this.libraryDependenciesTables = lazyMap(
siteId => asyncInstance(
() => CoreSites.getSiteTable(
LIBRARY_DEPENDENCIES_TABLE_NAME,
{
siteId,
config: { cachingStrategy: CoreDatabaseCachingStrategy.None },
onDestroy: () => delete this.libraryDependenciesTables[siteId],
},
),
),
);
this.contentsLibrariesTables = lazyMap(
siteId => asyncInstance(
() => CoreSites.getSiteTable(
CONTENTS_LIBRARIES_TABLE_NAME,
{
siteId,
config: { cachingStrategy: CoreDatabaseCachingStrategy.None },
onDestroy: () => delete this.contentsLibrariesTables[siteId],
},
),
),
);
this.librariesCachedAssetsTables = lazyMap(
siteId => asyncInstance(
() => CoreSites.getSiteTable(
LIBRARIES_CACHEDASSETS_TABLE_NAME,
{
siteId,
config: { cachingStrategy: CoreDatabaseCachingStrategy.None },
onDestroy: () => delete this.librariesCachedAssetsTables[siteId],
},
),
),
);
}
/** /**
* Will clear filtered params for all the content that uses the specified libraries. * Will clear filtered params for all the content that uses the specified libraries.
* This means that the content dependencies will have to be rebuilt and the parameters re-filtered. * This means that the content dependencies will have to be rebuilt and the parameters re-filtered.
@ -63,12 +136,19 @@ export class CoreH5PFramework {
return; return;
} }
const db = await CoreSites.getSiteDb(siteId); siteId ??= CoreSites.getCurrentSiteId();
const whereAndParams = SQLiteDB.getInOrEqual(libraryIds); const whereAndParams = SQLiteDB.getInOrEqual(libraryIds);
whereAndParams.sql = 'mainlibraryid ' + whereAndParams.sql; whereAndParams.sql = 'mainlibraryid ' + whereAndParams.sql;
await db.updateRecordsWhere(CONTENT_TABLE_NAME, { filtered: null }, whereAndParams.sql, whereAndParams.params); await this.contentTables[siteId].updateWhere(
{ filtered: null },
{
sql: whereAndParams.sql,
sqlParams: whereAndParams.params,
js: record => libraryIds.includes(record.mainlibraryid),
},
);
} }
/** /**
@ -79,20 +159,19 @@ export class CoreH5PFramework {
* @returns Promise resolved with the removed entries. * @returns Promise resolved with the removed entries.
*/ */
async deleteCachedAssets(libraryId: number, siteId?: string): Promise<CoreH5PLibraryCachedAssetsDBRecord[]> { async deleteCachedAssets(libraryId: number, siteId?: string): Promise<CoreH5PLibraryCachedAssetsDBRecord[]> {
siteId ??= CoreSites.getCurrentSiteId();
const db = await CoreSites.getSiteDb(siteId);
// Get all the hashes that use this library. // Get all the hashes that use this library.
const entries = await db.getRecords<CoreH5PLibraryCachedAssetsDBRecord>( const entries = await this.librariesCachedAssetsTables[siteId].getMany({ libraryid: libraryId });
LIBRARIES_CACHEDASSETS_TABLE_NAME,
{ libraryid: libraryId },
);
const hashes = entries.map((entry) => entry.hash); const hashes = entries.map((entry) => entry.hash);
if (hashes.length) { if (hashes.length) {
// Delete the entries from DB. // Delete the entries from DB.
await db.deleteRecordsList(LIBRARIES_CACHEDASSETS_TABLE_NAME, 'hash', hashes); await this.librariesCachedAssetsTables[siteId].deleteWhere({
sql: hashes.length === 1 ? 'hash = ?' : `hash IN (${hashes.map(() => '?').join(', ')})`,
sqlParams: hashes,
js: (record) => hashes.includes(record.hash),
});
} }
return entries; return entries;
@ -106,8 +185,7 @@ export class CoreH5PFramework {
* @returns Promise resolved when done. * @returns Promise resolved when done.
*/ */
async deleteContentData(id: number, siteId?: string): Promise<void> { async deleteContentData(id: number, siteId?: string): Promise<void> {
siteId ??= CoreSites.getCurrentSiteId();
const db = await CoreSites.getSiteDb(siteId);
// The user content should be reset (instead of removed), because this method is called when H5P content needs // The user content should be reset (instead of removed), because this method is called when H5P content needs
// to be updated too (and the previous states must be kept, but reset). // to be updated too (and the previous states must be kept, but reset).
@ -115,7 +193,7 @@ export class CoreH5PFramework {
await Promise.all([ await Promise.all([
// Delete the content data. // Delete the content data.
db.deleteRecords(CONTENT_TABLE_NAME, { id }), this.contentTables[siteId].deleteByPrimaryKey({ id }),
// Remove content library dependencies. // Remove content library dependencies.
this.deleteLibraryUsage(id, siteId), this.deleteLibraryUsage(id, siteId),
@ -130,9 +208,9 @@ export class CoreH5PFramework {
* @returns Promise resolved when done. * @returns Promise resolved when done.
*/ */
async deleteLibrary(id: number, siteId?: string): Promise<void> { async deleteLibrary(id: number, siteId?: string): Promise<void> {
const db = await CoreSites.getSiteDb(siteId); siteId ??= CoreSites.getCurrentSiteId();
await db.deleteRecords(LIBRARIES_TABLE_NAME, { id }); await this.librariesTables[siteId].deleteByPrimaryKey({ id });
} }
/** /**
@ -143,9 +221,9 @@ export class CoreH5PFramework {
* @returns Promise resolved when done. * @returns Promise resolved when done.
*/ */
async deleteLibraryDependencies(libraryId: number, siteId?: string): Promise<void> { async deleteLibraryDependencies(libraryId: number, siteId?: string): Promise<void> {
const db = await CoreSites.getSiteDb(siteId); siteId ??= CoreSites.getCurrentSiteId();
await db.deleteRecords(LIBRARY_DEPENDENCIES_TABLE_NAME, { libraryid: libraryId }); await this.libraryDependenciesTables[siteId].delete({ libraryid: libraryId });
} }
/** /**
@ -156,9 +234,9 @@ export class CoreH5PFramework {
* @returns Promise resolved when done. * @returns Promise resolved when done.
*/ */
async deleteLibraryUsage(id: number, siteId?: string): Promise<void> { async deleteLibraryUsage(id: number, siteId?: string): Promise<void> {
const db = await CoreSites.getSiteDb(siteId); siteId ??= CoreSites.getCurrentSiteId();
await db.deleteRecords(CONTENTS_LIBRARIES_TABLE_NAME, { h5pid: id }); await this.contentsLibrariesTables[siteId].delete({ h5pid: id });
} }
/** /**
@ -168,9 +246,9 @@ export class CoreH5PFramework {
* @returns Promise resolved with the list of content data. * @returns Promise resolved with the list of content data.
*/ */
async getAllContentData(siteId?: string): Promise<CoreH5PContentDBRecord[]> { async getAllContentData(siteId?: string): Promise<CoreH5PContentDBRecord[]> {
const db = await CoreSites.getSiteDb(siteId); siteId ??= CoreSites.getCurrentSiteId();
return db.getAllRecords<CoreH5PContentDBRecord>(CONTENT_TABLE_NAME); return this.contentTables[siteId].getMany();
} }
/** /**
@ -181,9 +259,9 @@ export class CoreH5PFramework {
* @returns Promise resolved with the content data. * @returns Promise resolved with the content data.
*/ */
async getContentData(id: number, siteId?: string): Promise<CoreH5PContentDBRecord> { async getContentData(id: number, siteId?: string): Promise<CoreH5PContentDBRecord> {
const db = await CoreSites.getSiteDb(siteId); siteId ??= CoreSites.getCurrentSiteId();
return db.getRecord<CoreH5PContentDBRecord>(CONTENT_TABLE_NAME, { id }); return this.contentTables[siteId].getOneByPrimaryKey({ id });
} }
/** /**
@ -194,18 +272,16 @@ export class CoreH5PFramework {
* @returns Promise resolved with the content data. * @returns Promise resolved with the content data.
*/ */
async getContentDataByUrl(fileUrl: string, siteId?: string): Promise<CoreH5PContentDBRecord> { async getContentDataByUrl(fileUrl: string, siteId?: string): Promise<CoreH5PContentDBRecord> {
const site = await CoreSites.getSite(siteId); siteId ??= CoreSites.getCurrentSiteId();
const db = site.getDb();
// Try to use the folder name, it should be more reliable than the URL. // Try to use the folder name, it should be more reliable than the URL.
const folderName = await CoreH5P.h5pCore.h5pFS.getContentFolderNameByUrl(fileUrl, site.getId()); const folderName = await CoreH5P.h5pCore.h5pFS.getContentFolderNameByUrl(fileUrl, siteId);
try { try {
return await db.getRecord<CoreH5PContentDBRecord>(CONTENT_TABLE_NAME, { foldername: folderName }); return await this.contentTables[siteId].getOne({ foldername: folderName });
} catch (error) { } catch (error) {
// Cannot get folder name, the h5p file was probably deleted. Just use the URL. // Cannot get folder name, the h5p file was probably deleted. Just use the URL.
return db.getRecord<CoreH5PContentDBRecord>(CONTENT_TABLE_NAME, { fileurl: fileUrl }); return await this.contentTables[siteId].getOne({ fileurl: fileUrl });
} }
} }
@ -216,17 +292,19 @@ export class CoreH5PFramework {
* @returns Promise resolved with the latest library version data. * @returns Promise resolved with the latest library version data.
*/ */
async getLatestLibraryVersion(machineName: string, siteId?: string): Promise<CoreH5PLibraryParsedDBRecord> { async getLatestLibraryVersion(machineName: string, siteId?: string): Promise<CoreH5PLibraryParsedDBRecord> {
siteId ??= CoreSites.getCurrentSiteId();
const db = await CoreSites.getSiteDb(siteId);
try { try {
const records = await db.getRecords<CoreH5PLibraryDBRecord>( const records = await this.librariesTables[siteId].getMany(
LIBRARIES_TABLE_NAME,
{ machinename: machineName }, { machinename: machineName },
'majorversion DESC, minorversion DESC, patchversion DESC', {
'*', limit: 1,
0, sorting: [
1, { majorversion: 'desc' },
{ minorversion: 'desc' },
{ patchversion: 'desc' },
],
},
); );
if (records && records[0]) { if (records && records[0]) {
@ -254,13 +332,12 @@ export class CoreH5PFramework {
minorVersion?: string | number, minorVersion?: string | number,
siteId?: string, siteId?: string,
): Promise<CoreH5PLibraryParsedDBRecord> { ): Promise<CoreH5PLibraryParsedDBRecord> {
siteId ??= CoreSites.getCurrentSiteId();
const db = await CoreSites.getSiteDb(siteId); const libraries = await this.librariesTables[siteId].getMany({
const libraries = await db.getRecords<CoreH5PLibraryDBRecord>(LIBRARIES_TABLE_NAME, {
machinename: machineName, machinename: machineName,
majorversion: majorVersion, majorversion: majorVersion !== undefined ? Number(majorVersion) : undefined,
minorversion: minorVersion, minorversion: minorVersion !== undefined ? Number(minorVersion) : undefined,
}); });
if (!libraries.length) { if (!libraries.length) {
@ -289,9 +366,9 @@ export class CoreH5PFramework {
* @returns Promise resolved with the library data, rejected if not found. * @returns Promise resolved with the library data, rejected if not found.
*/ */
async getLibraryById(id: number, siteId?: string): Promise<CoreH5PLibraryParsedDBRecord> { async getLibraryById(id: number, siteId?: string): Promise<CoreH5PLibraryParsedDBRecord> {
const db = await CoreSites.getSiteDb(siteId); siteId ??= CoreSites.getCurrentSiteId();
const library = await db.getRecord<CoreH5PLibraryDBRecord>(LIBRARIES_TABLE_NAME, { id }); const library = await this.librariesTables[siteId].getOneByPrimaryKey({ id });
return this.parseLibDBData(library); return this.parseLibDBData(library);
} }
@ -669,17 +746,14 @@ export class CoreH5PFramework {
folderName: string, folderName: string,
siteId?: string, siteId?: string,
): Promise<void> { ): Promise<void> {
const targetSiteId = siteId ?? CoreSites.getCurrentSiteId();
const db = await CoreSites.getSiteDb(siteId);
await Promise.all(Object.keys(dependencies).map(async (key) => { await Promise.all(Object.keys(dependencies).map(async (key) => {
const data: Partial<CoreH5PLibraryCachedAssetsDBRecord> = { await this.librariesCachedAssetsTables[targetSiteId].insert({
hash: key, hash: key,
libraryid: dependencies[key].libraryId, libraryid: dependencies[key].libraryId,
foldername: folderName, foldername: folderName,
}; });
await db.insertRecord(LIBRARIES_CACHEDASSETS_TABLE_NAME, data);
})); }));
} }
@ -691,6 +765,8 @@ export class CoreH5PFramework {
* @returns Promise resolved when done. * @returns Promise resolved when done.
*/ */
async saveLibraryData(libraryData: CoreH5PLibraryBeingSaved, siteId?: string): Promise<void> { async saveLibraryData(libraryData: CoreH5PLibraryBeingSaved, siteId?: string): Promise<void> {
siteId ??= CoreSites.getCurrentSiteId();
// Some special properties needs some checking and converting before they can be saved. // Some special properties needs some checking and converting before they can be saved.
const preloadedJS = this.libraryParameterValuesToCsv(libraryData, 'preloadedJs', 'path'); const preloadedJS = this.libraryParameterValuesToCsv(libraryData, 'preloadedJs', 'path');
const preloadedCSS = this.libraryParameterValuesToCsv(libraryData, 'preloadedCss', 'path'); const preloadedCSS = this.libraryParameterValuesToCsv(libraryData, 'preloadedCss', 'path');
@ -708,10 +784,7 @@ export class CoreH5PFramework {
embedTypes = libraryData.embedTypes.join(', '); embedTypes = libraryData.embedTypes.join(', ');
} }
const site = await CoreSites.getSite(siteId); const data: Omit<CoreH5PLibraryDBRecord, 'id'> & Partial<Pick<CoreH5PLibraryDBRecord, 'id'>> = {
const db = site.getDb();
const data: Partial<CoreH5PLibraryDBRecord> = {
title: libraryData.title, title: libraryData.title,
machinename: libraryData.machineName, machinename: libraryData.machineName,
majorversion: libraryData.majorVersion, majorversion: libraryData.majorVersion,
@ -733,16 +806,14 @@ export class CoreH5PFramework {
data.id = libraryData.libraryId; data.id = libraryData.libraryId;
} }
await db.insertRecord(LIBRARIES_TABLE_NAME, data); const libraryId = await this.librariesTables[siteId].insert(data);
if (!data.id) { if (!data.id) {
// New library. Get its ID. // New library. Get its ID.
const entry = await db.getRecord<CoreH5PLibraryDBRecord>(LIBRARIES_TABLE_NAME, data); libraryData.libraryId = libraryId;
libraryData.libraryId = entry.id;
} else { } else {
// Updated libary. Remove old dependencies. // Updated libary. Remove old dependencies.
await this.deleteLibraryDependencies(data.id, site.getId()); await this.deleteLibraryDependencies(data.id, siteId);
} }
} }
@ -761,8 +832,7 @@ export class CoreH5PFramework {
dependencyType: string, dependencyType: string,
siteId?: string, siteId?: string,
): Promise<void> { ): Promise<void> {
const targetSiteId = siteId ?? CoreSites.getCurrentSiteId();
const db = await CoreSites.getSiteDb(siteId);
await Promise.all(dependencies.map(async (dependency) => { await Promise.all(dependencies.map(async (dependency) => {
// Get the ID of the library. // Get the ID of the library.
@ -777,13 +847,15 @@ export class CoreH5PFramework {
} }
// Create the relation. // Create the relation.
const entry: Partial<CoreH5PLibraryDependencyDBRecord> = { if (typeof library.libraryId !== 'string') {
throw new CoreError('Attempted to create dependencies of library without id');
}
await this.libraryDependenciesTables[targetSiteId].insert({
libraryid: library.libraryId, libraryid: library.libraryId,
requiredlibraryid: dependencyId, requiredlibraryid: dependencyId,
dependencytype: dependencyType, dependencytype: dependencyType,
}; });
await db.insertRecord(LIBRARY_DEPENDENCIES_TABLE_NAME, entry);
})); }));
} }
@ -800,8 +872,7 @@ export class CoreH5PFramework {
librariesInUse: {[key: string]: CoreH5PContentDepsTreeDependency}, librariesInUse: {[key: string]: CoreH5PContentDepsTreeDependency},
siteId?: string, siteId?: string,
): Promise<void> { ): Promise<void> {
const targetSiteId = siteId ?? CoreSites.getCurrentSiteId();
const db = await CoreSites.getSiteDb(siteId);
// Calculate the CSS to drop. // Calculate the CSS to drop.
const dropLibraryCssList: Record<string, string> = {}; const dropLibraryCssList: Record<string, string> = {};
@ -818,18 +889,17 @@ export class CoreH5PFramework {
} }
} }
// Now save the uusage. // Now save the usage.
await Promise.all(Object.keys(librariesInUse).map((key) => { await Promise.all(Object.keys(librariesInUse).map((key) => {
const dependency = librariesInUse[key]; const dependency = librariesInUse[key];
const data: Partial<CoreH5PContentsLibraryDBRecord> = {
return this.contentsLibrariesTables[targetSiteId].insert({
h5pid: id, h5pid: id,
libraryid: dependency.library.libraryId, libraryid: dependency.library.libraryId,
dependencytype: dependency.type, dependencytype: dependency.type,
dropcss: dropLibraryCssList[dependency.library.machineName] ? 1 : 0, dropcss: dropLibraryCssList[dependency.library.machineName] ? 1 : 0,
weight: dependency.weight, weight: dependency.weight ?? 0,
}; });
return db.insertRecord(CONTENTS_LIBRARIES_TABLE_NAME, data);
})); }));
} }
@ -843,8 +913,7 @@ export class CoreH5PFramework {
* @returns Promise resolved with content ID. * @returns Promise resolved with content ID.
*/ */
async updateContent(content: CoreH5PContentBeingSaved, folderName: string, fileUrl: string, siteId?: string): Promise<number> { async updateContent(content: CoreH5PContentBeingSaved, folderName: string, fileUrl: string, siteId?: string): Promise<number> {
siteId ??= CoreSites.getCurrentSiteId();
const db = await CoreSites.getSiteDb(siteId);
// If the libraryid declared in the package is empty, get the latest version. // If the libraryid declared in the package is empty, get the latest version.
if (content.library && content.library.libraryId === undefined) { if (content.library && content.library.libraryId === undefined) {
@ -861,32 +930,31 @@ export class CoreH5PFramework {
content.params = JSON.stringify(params); content.params = JSON.stringify(params);
} }
const data: Partial<CoreH5PContentDBRecord> = { if (typeof content.library?.libraryId !== 'number') {
id: undefined, throw new CoreError('Attempted to create content of library without id');
jsoncontent: content.params, }
const data: Omit<CoreH5PContentDBRecord, 'id'> & Partial<Pick<CoreH5PContentDBRecord, 'id'>> = {
jsoncontent: content.params ?? '{}',
mainlibraryid: content.library?.libraryId, mainlibraryid: content.library?.libraryId,
timemodified: Date.now(), timemodified: Date.now(),
filtered: null, filtered: null,
foldername: folderName, foldername: folderName,
fileurl: fileUrl, fileurl: fileUrl,
timecreated: undefined, timecreated: Date.now(),
}; };
let contentId: number | undefined; let contentId: number | undefined;
if (content.id !== undefined) { if (content.id !== undefined) {
data.id = content.id; data.id = content.id;
contentId = content.id; contentId = content.id;
} else {
data.timecreated = data.timemodified;
} }
await db.insertRecord(CONTENT_TABLE_NAME, data); const newContentId = await this.contentTables[siteId].insert(data);
if (!contentId) { if (!contentId) {
// New content. Get its ID. // New content. Get its ID.
const entry = await db.getRecord<CoreH5PContentDBRecord>(CONTENT_TABLE_NAME, data); content.id = newContentId;
content.id = entry.id;
contentId = content.id; contentId = content.id;
} }
@ -901,12 +969,9 @@ export class CoreH5PFramework {
* @param siteId Site ID. If not defined, current site. * @param siteId Site ID. If not defined, current site.
*/ */
async updateContentFields(id: number, fields: Partial<CoreH5PContentDBRecord>, siteId?: string): Promise<void> { async updateContentFields(id: number, fields: Partial<CoreH5PContentDBRecord>, siteId?: string): Promise<void> {
siteId ??= CoreSites.getCurrentSiteId();
const db = await CoreSites.getSiteDb(siteId); await this.contentTables[siteId].update(fields, { id });
const data = Object.assign({}, fields);
await db.updateRecords(CONTENT_TABLE_NAME, data, { id });
} }
} }