MOBILE-3565 services: Move some DB vars and init to new files
parent
03f9723329
commit
6df1c2109d
|
@ -50,6 +50,11 @@ import { CoreTimeUtilsProvider } from '@services/utils/time';
|
|||
import { CoreUrlUtilsProvider } from '@services/utils/url';
|
||||
import { CoreUtilsProvider } from '@services/utils/utils';
|
||||
|
||||
// Import init DB functions of core services.
|
||||
import { initCoreFilepoolDB } from '@services/filepool.db';
|
||||
import { initCoreSitesDB } from '@services/sites.db';
|
||||
import { initCoreSyncDB } from '@services/sync.db';
|
||||
|
||||
// Import core modules.
|
||||
import { CoreEmulatorModule } from '@core/emulator/emulator.module';
|
||||
import { CoreLoginModule } from '@core/login/login.module';
|
||||
|
@ -121,6 +126,8 @@ export class AppModule {
|
|||
// Set the injector.
|
||||
setSingletonsInjector(injector);
|
||||
|
||||
this.initCoreServicesDB();
|
||||
|
||||
// Register a handler for platform ready.
|
||||
CoreInit.instance.registerProcess({
|
||||
name: 'CorePlatformReady',
|
||||
|
@ -154,4 +161,13 @@ export class AppModule {
|
|||
CoreInit.instance.executeInitProcesses();
|
||||
}
|
||||
|
||||
/**
|
||||
* Init the DB of core services.
|
||||
*/
|
||||
protected initCoreServicesDB(): void {
|
||||
initCoreFilepoolDB();
|
||||
initCoreSitesDB();
|
||||
initCoreSyncDB();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ import { CoreIonLoadingElement } from './ion-loading';
|
|||
/**
|
||||
* Class that represents a site (combination of site + user).
|
||||
* It will have all the site data and provide utility functions regarding a site.
|
||||
* To add tables to the site's database, please use CoreSitesProvider.registerSiteSchema. This will make sure that
|
||||
* To add tables to the site's database, please use registerSiteSchema exported in @services/sites.ts. This will make sure that
|
||||
* the tables are created in all the sites, not just the current one.
|
||||
*
|
||||
* @todo: Refactor this class to improve "temporary" sites support (not fully authenticated).
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { SQLiteDBTableSchema } from '@classes/sqlitedb';
|
||||
|
||||
/**
|
||||
* Database variables for CoreApp service.
|
||||
*/
|
||||
export const DBNAME = 'MoodleMobile';
|
||||
export const SCHEMA_VERSIONS_TABLE_NAME = 'schema_versions';
|
||||
|
||||
export const SCHEMA_VERSIONS_TABLE_SCHEMA: SQLiteDBTableSchema = {
|
||||
name: SCHEMA_VERSIONS_TABLE_NAME,
|
||||
columns: [
|
||||
{
|
||||
name: 'name',
|
||||
type: 'TEXT',
|
||||
primaryKey: true,
|
||||
},
|
||||
{
|
||||
name: 'version',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export type SchemaVersionsDBEntry = {
|
||||
name: string;
|
||||
version: number;
|
||||
};
|
|
@ -24,9 +24,7 @@ import { CoreConstants } from '@core/constants';
|
|||
|
||||
import { makeSingleton, Keyboard, Network, StatusBar, Platform } from '@singletons/core.singletons';
|
||||
import { CoreLogger } from '@singletons/logger';
|
||||
|
||||
const DBNAME = 'MoodleMobile';
|
||||
const SCHEMA_VERSIONS_TABLE = 'schema_versions';
|
||||
import { DBNAME, SCHEMA_VERSIONS_TABLE_NAME, SCHEMA_VERSIONS_TABLE_SCHEMA, SchemaVersionsDBEntry } from '@services/app.db';
|
||||
|
||||
/**
|
||||
* Factory to provide some global functionalities, like access to the global app database.
|
||||
|
@ -57,27 +55,13 @@ export class CoreAppProvider {
|
|||
|
||||
// Variables for DB.
|
||||
protected createVersionsTableReady: Promise<void>;
|
||||
protected versionsTableSchema: SQLiteDBTableSchema = {
|
||||
name: SCHEMA_VERSIONS_TABLE,
|
||||
columns: [
|
||||
{
|
||||
name: 'name',
|
||||
type: 'TEXT',
|
||||
primaryKey: true,
|
||||
},
|
||||
{
|
||||
name: 'version',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
constructor(appRef: ApplicationRef, zone: NgZone) {
|
||||
this.logger = CoreLogger.getInstance('CoreAppProvider');
|
||||
this.db = CoreDB.instance.getDB(DBNAME);
|
||||
|
||||
// Create the schema versions table.
|
||||
this.createVersionsTableReady = this.db.createTableFromSchema(this.versionsTableSchema);
|
||||
this.createVersionsTableReady = this.db.createTableFromSchema(SCHEMA_VERSIONS_TABLE_SCHEMA);
|
||||
|
||||
Keyboard.instance.onKeyboardShow().subscribe((data) => {
|
||||
// Execute the callback in the Angular zone, so change detection doesn't stop working.
|
||||
|
@ -175,7 +159,7 @@ export class CoreAppProvider {
|
|||
await this.createVersionsTableReady;
|
||||
|
||||
// Fetch installed version of the schema.
|
||||
const entry = await this.db.getRecord<SchemaVersionsDBEntry>(SCHEMA_VERSIONS_TABLE, { name: schema.name });
|
||||
const entry = await this.db.getRecord<SchemaVersionsDBEntry>(SCHEMA_VERSIONS_TABLE_NAME, { name: schema.name });
|
||||
|
||||
oldVersion = entry.version;
|
||||
} catch (error) {
|
||||
|
@ -198,7 +182,7 @@ export class CoreAppProvider {
|
|||
}
|
||||
|
||||
// Set installed version.
|
||||
await this.db.insertRecord(SCHEMA_VERSIONS_TABLE, { name: schema.name, version: schema.version });
|
||||
await this.db.insertRecord(SCHEMA_VERSIONS_TABLE_NAME, { name: schema.name, version: schema.version });
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -741,8 +725,3 @@ export type WindowForAutomatedTests = Window & {
|
|||
appProvider?: CoreAppProvider;
|
||||
appRef?: ApplicationRef;
|
||||
};
|
||||
|
||||
type SchemaVersionsDBEntry = {
|
||||
name: string;
|
||||
version: number;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { CoreAppSchema } from '@services/app';
|
||||
|
||||
/**
|
||||
* Database variables for for CoreConfig service.
|
||||
*/
|
||||
export const CONFIG_TABLE_NAME = 'core_config';
|
||||
|
||||
export const APP_SCHEMA: CoreAppSchema = {
|
||||
name: 'CoreConfigProvider',
|
||||
version: 1,
|
||||
tables: [
|
||||
{
|
||||
name: CONFIG_TABLE_NAME,
|
||||
columns: [
|
||||
{
|
||||
name: 'name',
|
||||
type: 'TEXT',
|
||||
unique: true,
|
||||
notNull: true,
|
||||
},
|
||||
{
|
||||
name: 'value',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export type ConfigDBEntry = {
|
||||
name: string;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
value: any;
|
||||
};
|
|
@ -14,11 +14,10 @@
|
|||
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
import { CoreApp, CoreAppSchema } from '@services/app';
|
||||
import { CoreApp } from '@services/app';
|
||||
import { SQLiteDB } from '@classes/sqlitedb';
|
||||
import { makeSingleton } from '@singletons/core.singletons';
|
||||
|
||||
const TABLE_NAME = 'core_config';
|
||||
import { CONFIG_TABLE_NAME, APP_SCHEMA, ConfigDBEntry } from '@services/config.db';
|
||||
|
||||
/**
|
||||
* Factory to provide access to dynamic and permanent config and settings.
|
||||
|
@ -28,32 +27,11 @@ const TABLE_NAME = 'core_config';
|
|||
export class CoreConfigProvider {
|
||||
|
||||
protected appDB: SQLiteDB;
|
||||
protected tableSchema: CoreAppSchema = {
|
||||
name: 'CoreConfigProvider',
|
||||
version: 1,
|
||||
tables: [
|
||||
{
|
||||
name: TABLE_NAME,
|
||||
columns: [
|
||||
{
|
||||
name: 'name',
|
||||
type: 'TEXT',
|
||||
unique: true,
|
||||
notNull: true,
|
||||
},
|
||||
{
|
||||
name: 'value',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
protected dbReady: Promise<void>; // Promise resolved when the app DB is initialized.
|
||||
|
||||
constructor() {
|
||||
this.appDB = CoreApp.instance.getDB();
|
||||
this.dbReady = CoreApp.instance.createTablesFromSchema(this.tableSchema).catch(() => {
|
||||
this.dbReady = CoreApp.instance.createTablesFromSchema(APP_SCHEMA).catch(() => {
|
||||
// Ignore errors.
|
||||
});
|
||||
}
|
||||
|
@ -67,7 +45,7 @@ export class CoreConfigProvider {
|
|||
async delete(name: string): Promise<void> {
|
||||
await this.dbReady;
|
||||
|
||||
await this.appDB.deleteRecords(TABLE_NAME, { name });
|
||||
await this.appDB.deleteRecords(CONFIG_TABLE_NAME, { name });
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -81,7 +59,7 @@ export class CoreConfigProvider {
|
|||
await this.dbReady;
|
||||
|
||||
try {
|
||||
const entry = await this.appDB.getRecord<ConfigDBEntry>(TABLE_NAME, { name });
|
||||
const entry = await this.appDB.getRecord<ConfigDBEntry>(CONFIG_TABLE_NAME, { name });
|
||||
|
||||
return entry.value;
|
||||
} catch (error) {
|
||||
|
@ -103,15 +81,9 @@ export class CoreConfigProvider {
|
|||
async set(name: string, value: number | string): Promise<void> {
|
||||
await this.dbReady;
|
||||
|
||||
await this.appDB.insertRecord(TABLE_NAME, { name, value });
|
||||
await this.appDB.insertRecord(CONFIG_TABLE_NAME, { name, value });
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class CoreConfig extends makeSingleton(CoreConfigProvider) {}
|
||||
|
||||
type ConfigDBEntry = {
|
||||
name: string;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
value: any;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { CoreAppSchema } from '@services/app';
|
||||
|
||||
/**
|
||||
* Database variables for CoreCron service.
|
||||
*/
|
||||
export const CRON_TABLE_NAME = 'cron';
|
||||
export const APP_SCHEMA: CoreAppSchema = {
|
||||
name: 'CoreCronDelegate',
|
||||
version: 1,
|
||||
tables: [
|
||||
{
|
||||
name: CRON_TABLE_NAME,
|
||||
columns: [
|
||||
{
|
||||
name: 'id',
|
||||
type: 'TEXT',
|
||||
primaryKey: true,
|
||||
},
|
||||
{
|
||||
name: 'value',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export type CronDBEntry = {
|
||||
id: string;
|
||||
value: number;
|
||||
};
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
import { Injectable, NgZone } from '@angular/core';
|
||||
|
||||
import { CoreApp, CoreAppProvider, CoreAppSchema } from '@services/app';
|
||||
import { CoreApp, CoreAppProvider } from '@services/app';
|
||||
import { CoreConfig } from '@services/config';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { CoreConstants } from '@core/constants';
|
||||
|
@ -23,8 +23,7 @@ import { CoreError } from '@classes/errors/error';
|
|||
|
||||
import { makeSingleton, Network } from '@singletons/core.singletons';
|
||||
import { CoreLogger } from '@singletons/logger';
|
||||
|
||||
const CRON_TABLE = 'cron';
|
||||
import { APP_SCHEMA, CRON_TABLE_NAME, CronDBEntry } from '@services/cron.db';
|
||||
|
||||
/*
|
||||
* Service to handle cron processes. The registered processes will be executed every certain time.
|
||||
|
@ -37,28 +36,6 @@ export class CoreCronDelegate {
|
|||
static readonly MIN_INTERVAL = 300000; // Minimum interval is 5 minutes.
|
||||
static readonly MAX_TIME_PROCESS = 120000; // Max time a process can block the queue. Defaults to 2 minutes.
|
||||
|
||||
// Variables for database.
|
||||
protected tableSchema: CoreAppSchema = {
|
||||
name: 'CoreCronDelegate',
|
||||
version: 1,
|
||||
tables: [
|
||||
{
|
||||
name: CRON_TABLE,
|
||||
columns: [
|
||||
{
|
||||
name: 'id',
|
||||
type: 'TEXT',
|
||||
primaryKey: true,
|
||||
},
|
||||
{
|
||||
name: 'value',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
protected logger: CoreLogger;
|
||||
protected appDB: SQLiteDB;
|
||||
protected dbReady: Promise<void>; // Promise resolved when the app DB is initialized.
|
||||
|
@ -69,7 +46,7 @@ export class CoreCronDelegate {
|
|||
this.logger = CoreLogger.getInstance('CoreCronDelegate');
|
||||
|
||||
this.appDB = CoreApp.instance.getDB();
|
||||
this.dbReady = CoreApp.instance.createTablesFromSchema(this.tableSchema).catch(() => {
|
||||
this.dbReady = CoreApp.instance.createTablesFromSchema(APP_SCHEMA).catch(() => {
|
||||
// Ignore errors.
|
||||
});
|
||||
|
||||
|
@ -268,7 +245,7 @@ export class CoreCronDelegate {
|
|||
const id = this.getHandlerLastExecutionId(name);
|
||||
|
||||
try {
|
||||
const entry = await this.appDB.getRecord<CronDBEntry>(CRON_TABLE, { id });
|
||||
const entry = await this.appDB.getRecord<CronDBEntry>(CRON_TABLE_NAME, { id });
|
||||
|
||||
const time = Number(entry.value);
|
||||
|
||||
|
@ -431,7 +408,7 @@ export class CoreCronDelegate {
|
|||
value: time,
|
||||
};
|
||||
|
||||
await this.appDB.insertRecord(CRON_TABLE, entry);
|
||||
await this.appDB.insertRecord(CRON_TABLE_NAME, entry);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -562,8 +539,3 @@ export interface CoreCronHandler {
|
|||
export type WindowForAutomatedTests = Window & {
|
||||
cronProvider?: CoreCronDelegate;
|
||||
};
|
||||
|
||||
type CronDBEntry = {
|
||||
id: string;
|
||||
value: number;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,367 @@
|
|||
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { CoreAppSchema } from '@services/app';
|
||||
import { CoreSiteSchema, registerSiteSchema } from '@services/sites';
|
||||
|
||||
/**
|
||||
* Database variables for CoreFilepool service.
|
||||
*/
|
||||
export const QUEUE_TABLE_NAME = 'filepool_files_queue'; // Queue of files to download.
|
||||
export const FILES_TABLE_NAME = 'filepool_files'; // Downloaded files.
|
||||
export const LINKS_TABLE_NAME = 'filepool_files_links'; // Links between downloaded files and components.
|
||||
export const PACKAGES_TABLE_NAME = 'filepool_packages'; // Downloaded packages (sets of files).
|
||||
export const APP_SCHEMA: CoreAppSchema = {
|
||||
name: 'CoreFilepoolProvider',
|
||||
version: 1,
|
||||
tables: [
|
||||
{
|
||||
name: QUEUE_TABLE_NAME,
|
||||
columns: [
|
||||
{
|
||||
name: 'siteId',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'fileId',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'added',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'priority',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'url',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'revision',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'timemodified',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'isexternalfile',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'repositorytype',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'path',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'links',
|
||||
type: 'TEXT',
|
||||
},
|
||||
],
|
||||
primaryKeys: ['siteId', 'fileId'],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const SITE_SCHEMA: CoreSiteSchema = {
|
||||
name: 'CoreFilepoolProvider',
|
||||
version: 1,
|
||||
tables: [
|
||||
{
|
||||
name: FILES_TABLE_NAME,
|
||||
columns: [
|
||||
{
|
||||
name: 'fileId',
|
||||
type: 'TEXT',
|
||||
primaryKey: true,
|
||||
},
|
||||
{
|
||||
name: 'url',
|
||||
type: 'TEXT',
|
||||
notNull: true,
|
||||
},
|
||||
{
|
||||
name: 'revision',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'timemodified',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'stale',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'downloadTime',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'isexternalfile',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'repositorytype',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'path',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'extension',
|
||||
type: 'TEXT',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: LINKS_TABLE_NAME,
|
||||
columns: [
|
||||
{
|
||||
name: 'fileId',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'component',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'componentId',
|
||||
type: 'TEXT',
|
||||
},
|
||||
],
|
||||
primaryKeys: ['fileId', 'component', 'componentId'],
|
||||
},
|
||||
{
|
||||
name: PACKAGES_TABLE_NAME,
|
||||
columns: [
|
||||
{
|
||||
name: 'id',
|
||||
type: 'TEXT',
|
||||
primaryKey: true,
|
||||
},
|
||||
{
|
||||
name: 'component',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'componentId',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'status',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'previous',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'updated',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'downloadTime',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'previousDownloadTime',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'extra',
|
||||
type: 'TEXT',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
/**
|
||||
* File options.
|
||||
*/
|
||||
export type CoreFilepoolFileOptions = {
|
||||
revision?: number; // File's revision.
|
||||
timemodified?: number; // File's timemodified.
|
||||
isexternalfile?: number; // 1 if it's a external file (from an external repository), 0 otherwise.
|
||||
repositorytype?: string; // Type of the repository this file belongs to.
|
||||
};
|
||||
|
||||
/**
|
||||
* Entry from filepool.
|
||||
*/
|
||||
export type CoreFilepoolFileEntry = CoreFilepoolFileOptions & {
|
||||
/**
|
||||
* The fileId to identify the file.
|
||||
*/
|
||||
fileId: string;
|
||||
|
||||
/**
|
||||
* File's URL.
|
||||
*/
|
||||
url: string;
|
||||
|
||||
/**
|
||||
* 1 if file is stale (needs to be updated), 0 otherwise.
|
||||
*/
|
||||
stale: number;
|
||||
|
||||
/**
|
||||
* Timestamp when this file was downloaded.
|
||||
*/
|
||||
downloadTime: number;
|
||||
|
||||
/**
|
||||
* File's path.
|
||||
*/
|
||||
path: string;
|
||||
|
||||
/**
|
||||
* File's extension.
|
||||
*/
|
||||
extension: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* DB data for entry from file's queue.
|
||||
*/
|
||||
export type CoreFilepoolQueueDBEntry = CoreFilepoolFileOptions & {
|
||||
/**
|
||||
* The site the file belongs to.
|
||||
*/
|
||||
siteId: string;
|
||||
|
||||
/**
|
||||
* The fileId to identify the file.
|
||||
*/
|
||||
fileId: string;
|
||||
|
||||
/**
|
||||
* Timestamp when the file was added to the queue.
|
||||
*/
|
||||
added: number;
|
||||
|
||||
/**
|
||||
* The priority of the file.
|
||||
*/
|
||||
priority: number;
|
||||
|
||||
/**
|
||||
* File's URL.
|
||||
*/
|
||||
url: string;
|
||||
|
||||
/**
|
||||
* File's path.
|
||||
*/
|
||||
path?: string;
|
||||
|
||||
/**
|
||||
* File links (to link the file to components and componentIds). Serialized to store on DB.
|
||||
*/
|
||||
links: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Entry from the file's queue.
|
||||
*/
|
||||
export type CoreFilepoolQueueEntry = CoreFilepoolQueueDBEntry & {
|
||||
/**
|
||||
* File links (to link the file to components and componentIds).
|
||||
*/
|
||||
linksUnserialized?: CoreFilepoolComponentLink[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Entry from packages table.
|
||||
*/
|
||||
export type CoreFilepoolPackageEntry = {
|
||||
/**
|
||||
* Package id.
|
||||
*/
|
||||
id?: string;
|
||||
|
||||
/**
|
||||
* The component to link the files to.
|
||||
*/
|
||||
component?: string;
|
||||
|
||||
/**
|
||||
* An ID to use in conjunction with the component.
|
||||
*/
|
||||
componentId?: string | number;
|
||||
|
||||
/**
|
||||
* Package status.
|
||||
*/
|
||||
status?: string;
|
||||
|
||||
/**
|
||||
* Package previous status.
|
||||
*/
|
||||
previous?: string;
|
||||
|
||||
/**
|
||||
* Timestamp when this package was updated.
|
||||
*/
|
||||
updated?: number;
|
||||
|
||||
/**
|
||||
* Timestamp when this package was downloaded.
|
||||
*/
|
||||
downloadTime?: number;
|
||||
|
||||
/**
|
||||
* Previous download time.
|
||||
*/
|
||||
previousDownloadTime?: number;
|
||||
|
||||
/**
|
||||
* Extra data stored by the package.
|
||||
*/
|
||||
extra?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* A component link.
|
||||
*/
|
||||
export type CoreFilepoolComponentLink = {
|
||||
/**
|
||||
* Link's component.
|
||||
*/
|
||||
component: string;
|
||||
|
||||
/**
|
||||
* Link's componentId.
|
||||
*/
|
||||
componentId?: string | number;
|
||||
};
|
||||
|
||||
/**
|
||||
* Links table record type.
|
||||
*/
|
||||
export type CoreFilepoolLinksRecord = {
|
||||
fileId: string; // File Id.
|
||||
component: string; // Component name.
|
||||
componentId: number | string; // Component Id.
|
||||
};
|
||||
|
||||
export const initCoreFilepoolDB = (): void => {
|
||||
registerSiteSchema(SITE_SCHEMA);
|
||||
};
|
|
@ -15,12 +15,12 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { Md5 } from 'ts-md5/dist/md5';
|
||||
|
||||
import { CoreApp, CoreAppSchema } from '@services/app';
|
||||
import { CoreApp } from '@services/app';
|
||||
import { CoreEvents } from '@singletons/events';
|
||||
import { CoreFile } from '@services/file';
|
||||
import { CoreInit } from '@services/init';
|
||||
import { CorePluginFile } from '@services/plugin-file-delegate';
|
||||
import { CoreSites, CoreSiteSchema } from '@services/sites';
|
||||
import { CoreSites } from '@services/sites';
|
||||
import { CoreWS, CoreWSExternalFile } from '@services/ws';
|
||||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
import { CoreMimetypeUtils } from '@services/utils/mimetype';
|
||||
|
@ -33,6 +33,20 @@ import { CoreError } from '@classes/errors/error';
|
|||
import { CoreConstants } from '@core/constants';
|
||||
import { makeSingleton, Network, NgZone, Translate } from '@singletons/core.singletons';
|
||||
import { CoreLogger } from '@singletons/logger';
|
||||
import {
|
||||
APP_SCHEMA,
|
||||
FILES_TABLE_NAME,
|
||||
QUEUE_TABLE_NAME,
|
||||
PACKAGES_TABLE_NAME,
|
||||
LINKS_TABLE_NAME,
|
||||
CoreFilepoolFileEntry,
|
||||
CoreFilepoolComponentLink,
|
||||
CoreFilepoolFileOptions,
|
||||
CoreFilepoolLinksRecord,
|
||||
CoreFilepoolPackageEntry,
|
||||
CoreFilepoolQueueEntry,
|
||||
CoreFilepoolQueueDBEntry,
|
||||
} from '@services/filepool.db';
|
||||
|
||||
/*
|
||||
* Factory for handling downloading files and retrieve downloaded files.
|
||||
|
@ -60,182 +74,6 @@ export class CoreFilepoolProvider {
|
|||
protected static readonly FILE_UPDATE_UNKNOWN_WHERE_CLAUSE =
|
||||
'isexternalfile = 1 OR ((revision IS NULL OR revision = 0) AND (timemodified IS NULL OR timemodified = 0))';
|
||||
|
||||
// Variables for database.
|
||||
protected static readonly QUEUE_TABLE = 'filepool_files_queue'; // Queue of files to download.
|
||||
protected static readonly FILES_TABLE = 'filepool_files'; // Downloaded files.
|
||||
protected static readonly LINKS_TABLE = 'filepool_files_links'; // Links between downloaded files and components.
|
||||
protected static readonly PACKAGES_TABLE = 'filepool_packages'; // Downloaded packages (sets of files).
|
||||
protected appTablesSchema: CoreAppSchema = {
|
||||
name: 'CoreFilepoolProvider',
|
||||
version: 1,
|
||||
tables: [
|
||||
{
|
||||
name: CoreFilepoolProvider.QUEUE_TABLE,
|
||||
columns: [
|
||||
{
|
||||
name: 'siteId',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'fileId',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'added',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'priority',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'url',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'revision',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'timemodified',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'isexternalfile',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'repositorytype',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'path',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'links',
|
||||
type: 'TEXT',
|
||||
},
|
||||
],
|
||||
primaryKeys: ['siteId', 'fileId'],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
protected siteSchema: CoreSiteSchema = {
|
||||
name: 'CoreFilepoolProvider',
|
||||
version: 1,
|
||||
tables: [
|
||||
{
|
||||
name: CoreFilepoolProvider.FILES_TABLE,
|
||||
columns: [
|
||||
{
|
||||
name: 'fileId',
|
||||
type: 'TEXT',
|
||||
primaryKey: true,
|
||||
},
|
||||
{
|
||||
name: 'url',
|
||||
type: 'TEXT',
|
||||
notNull: true,
|
||||
},
|
||||
{
|
||||
name: 'revision',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'timemodified',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'stale',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'downloadTime',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'isexternalfile',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'repositorytype',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'path',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'extension',
|
||||
type: 'TEXT',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: CoreFilepoolProvider.LINKS_TABLE,
|
||||
columns: [
|
||||
{
|
||||
name: 'fileId',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'component',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'componentId',
|
||||
type: 'TEXT',
|
||||
},
|
||||
],
|
||||
primaryKeys: ['fileId', 'component', 'componentId'],
|
||||
},
|
||||
{
|
||||
name: CoreFilepoolProvider.PACKAGES_TABLE,
|
||||
columns: [
|
||||
{
|
||||
name: 'id',
|
||||
type: 'TEXT',
|
||||
primaryKey: true,
|
||||
},
|
||||
{
|
||||
name: 'component',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'componentId',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'status',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'previous',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'updated',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'downloadTime',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'previousDownloadTime',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'extra',
|
||||
type: 'TEXT',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
protected logger: CoreLogger;
|
||||
protected appDB: SQLiteDB;
|
||||
protected dbReady: Promise<void>; // Promise resolved when the app DB is initialized.
|
||||
|
@ -258,12 +96,10 @@ export class CoreFilepoolProvider {
|
|||
this.logger = CoreLogger.getInstance('CoreFilepoolProvider');
|
||||
|
||||
this.appDB = CoreApp.instance.getDB();
|
||||
this.dbReady = CoreApp.instance.createTablesFromSchema(this.appTablesSchema).catch(() => {
|
||||
this.dbReady = CoreApp.instance.createTablesFromSchema(APP_SCHEMA).catch(() => {
|
||||
// Ignore errors.
|
||||
});
|
||||
|
||||
CoreSites.instance.registerSiteSchema(this.siteSchema);
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
|
@ -308,7 +144,7 @@ export class CoreFilepoolProvider {
|
|||
componentId: componentId || '',
|
||||
};
|
||||
|
||||
await db.insertRecord(CoreFilepoolProvider.LINKS_TABLE, newEntry);
|
||||
await db.insertRecord(LINKS_TABLE_NAME, newEntry);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -373,7 +209,7 @@ export class CoreFilepoolProvider {
|
|||
|
||||
const db = await CoreSites.instance.getSiteDb(siteId);
|
||||
|
||||
await db.insertRecord(CoreFilepoolProvider.FILES_TABLE, record);
|
||||
await db.insertRecord(FILES_TABLE_NAME, record);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -433,7 +269,7 @@ export class CoreFilepoolProvider {
|
|||
|
||||
this.logger.debug(`Adding ${fileId} to the queue`);
|
||||
|
||||
await this.appDB.insertRecord(CoreFilepoolProvider.QUEUE_TABLE, {
|
||||
await this.appDB.insertRecord(QUEUE_TABLE_NAME, {
|
||||
siteId,
|
||||
fileId,
|
||||
url,
|
||||
|
@ -563,7 +399,7 @@ export class CoreFilepoolProvider {
|
|||
// Update only when required.
|
||||
this.logger.debug(`Updating file ${fileId} which is already in queue`);
|
||||
|
||||
return this.appDB.updateRecords(CoreFilepoolProvider.QUEUE_TABLE, newData, primaryKey).then(() =>
|
||||
return this.appDB.updateRecords(QUEUE_TABLE_NAME, newData, primaryKey).then(() =>
|
||||
this.getQueuePromise(siteId, fileId, true, onProgress));
|
||||
}
|
||||
|
||||
|
@ -692,9 +528,9 @@ export class CoreFilepoolProvider {
|
|||
|
||||
const site = await CoreSites.instance.getSite(siteId);
|
||||
// Get all the packages to be able to "notify" the change in the status.
|
||||
const entries: CoreFilepoolPackageEntry[] = await site.getDb().getAllRecords(CoreFilepoolProvider.PACKAGES_TABLE);
|
||||
const entries: CoreFilepoolPackageEntry[] = await site.getDb().getAllRecords(PACKAGES_TABLE_NAME);
|
||||
// Delete all the entries.
|
||||
await site.getDb().deleteRecords(CoreFilepoolProvider.PACKAGES_TABLE);
|
||||
await site.getDb().deleteRecords(PACKAGES_TABLE_NAME);
|
||||
|
||||
entries.forEach((entry) => {
|
||||
// Trigger module status changed, setting it as not downloaded.
|
||||
|
@ -712,8 +548,8 @@ export class CoreFilepoolProvider {
|
|||
const db = await CoreSites.instance.getSiteDb(siteId);
|
||||
|
||||
await Promise.all([
|
||||
db.deleteRecords(CoreFilepoolProvider.FILES_TABLE),
|
||||
db.deleteRecords(CoreFilepoolProvider.LINKS_TABLE),
|
||||
db.deleteRecords(FILES_TABLE_NAME),
|
||||
db.deleteRecords(LINKS_TABLE_NAME),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -732,7 +568,7 @@ export class CoreFilepoolProvider {
|
|||
componentId: this.fixComponentId(componentId),
|
||||
};
|
||||
|
||||
const count = await db.countRecords(CoreFilepoolProvider.LINKS_TABLE, conditions);
|
||||
const count = await db.countRecords(LINKS_TABLE_NAME, conditions);
|
||||
if (count <= 0) {
|
||||
throw new CoreError('Component doesn\'t have files');
|
||||
}
|
||||
|
@ -1257,7 +1093,7 @@ export class CoreFilepoolProvider {
|
|||
// Minor problem: file will remain in the filesystem once downloaded again.
|
||||
this.logger.debug('Staled file with no extension ' + entry.fileId);
|
||||
|
||||
await db.updateRecords(CoreFilepoolProvider.FILES_TABLE, { stale: 1 }, { fileId: entry.fileId });
|
||||
await db.updateRecords(FILES_TABLE_NAME, { stale: 1 }, { fileId: entry.fileId });
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -1267,7 +1103,7 @@ export class CoreFilepoolProvider {
|
|||
entry.fileId = CoreMimetypeUtils.instance.removeExtension(fileId);
|
||||
entry.extension = extension;
|
||||
|
||||
await db.updateRecords(CoreFilepoolProvider.FILES_TABLE, entry, { fileId });
|
||||
await db.updateRecords(FILES_TABLE_NAME, entry, { fileId });
|
||||
if (entry.fileId == fileId) {
|
||||
// File ID hasn't changed, we're done.
|
||||
this.logger.debug('Removed extesion ' + extension + ' from file ' + entry.fileId);
|
||||
|
@ -1276,7 +1112,7 @@ export class CoreFilepoolProvider {
|
|||
}
|
||||
|
||||
// Now update the links.
|
||||
await db.updateRecords(CoreFilepoolProvider.LINKS_TABLE, { fileId: entry.fileId }, { fileId });
|
||||
await db.updateRecords(LINKS_TABLE_NAME, { fileId: entry.fileId }, { fileId });
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1339,7 +1175,7 @@ export class CoreFilepoolProvider {
|
|||
componentId: this.fixComponentId(componentId),
|
||||
};
|
||||
|
||||
const items = await db.getRecords<CoreFilepoolLinksRecord>(CoreFilepoolProvider.LINKS_TABLE, conditions);
|
||||
const items = await db.getRecords<CoreFilepoolLinksRecord>(LINKS_TABLE_NAME, conditions);
|
||||
items.forEach((item) => {
|
||||
item.componentId = this.fixComponentId(item.componentId);
|
||||
});
|
||||
|
@ -1449,7 +1285,7 @@ export class CoreFilepoolProvider {
|
|||
*/
|
||||
protected async getFileLinks(siteId: string, fileId: string): Promise<CoreFilepoolLinksRecord[]> {
|
||||
const db = await CoreSites.instance.getSiteDb(siteId);
|
||||
const items = await db.getRecords<CoreFilepoolLinksRecord>(CoreFilepoolProvider.LINKS_TABLE, { fileId });
|
||||
const items = await db.getRecords<CoreFilepoolLinksRecord>(LINKS_TABLE_NAME, { fileId });
|
||||
|
||||
items.forEach((item) => {
|
||||
item.componentId = this.fixComponentId(item.componentId);
|
||||
|
@ -1527,7 +1363,7 @@ export class CoreFilepoolProvider {
|
|||
await Promise.all(items.map(async (item) => {
|
||||
try {
|
||||
const fileEntry = await db.getRecord<CoreFilepoolFileEntry>(
|
||||
CoreFilepoolProvider.FILES_TABLE,
|
||||
FILES_TABLE_NAME,
|
||||
{ fileId: item.fileId },
|
||||
);
|
||||
|
||||
|
@ -1808,7 +1644,7 @@ export class CoreFilepoolProvider {
|
|||
const site = await CoreSites.instance.getSite(siteId);
|
||||
const packageId = this.getPackageId(component, componentId);
|
||||
|
||||
return site.getDb().getRecord(CoreFilepoolProvider.PACKAGES_TABLE, { id: packageId });
|
||||
return site.getDb().getRecord(PACKAGES_TABLE_NAME, { id: packageId });
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2258,7 +2094,7 @@ export class CoreFilepoolProvider {
|
|||
*/
|
||||
protected async hasFileInPool(siteId: string, fileId: string): Promise<CoreFilepoolFileEntry> {
|
||||
const db = await CoreSites.instance.getSiteDb(siteId);
|
||||
const entry = await db.getRecord<CoreFilepoolFileEntry>(CoreFilepoolProvider.FILES_TABLE, { fileId });
|
||||
const entry = await db.getRecord<CoreFilepoolFileEntry>(FILES_TABLE_NAME, { fileId });
|
||||
|
||||
if (typeof entry === 'undefined') {
|
||||
throw new CoreError('File not found in filepool.');
|
||||
|
@ -2277,7 +2113,7 @@ export class CoreFilepoolProvider {
|
|||
protected async hasFileInQueue(siteId: string, fileId: string): Promise<CoreFilepoolQueueEntry> {
|
||||
await this.dbReady;
|
||||
|
||||
const entry = await this.appDB.getRecord<CoreFilepoolQueueEntry>(CoreFilepoolProvider.QUEUE_TABLE, { siteId, fileId });
|
||||
const entry = await this.appDB.getRecord<CoreFilepoolQueueEntry>(QUEUE_TABLE_NAME, { siteId, fileId });
|
||||
|
||||
if (typeof entry === 'undefined') {
|
||||
throw new CoreError('File not found in queue.');
|
||||
|
@ -2301,7 +2137,7 @@ export class CoreFilepoolProvider {
|
|||
|
||||
const where = onlyUnknown ? CoreFilepoolProvider.FILE_UPDATE_UNKNOWN_WHERE_CLAUSE : undefined;
|
||||
|
||||
await db.updateRecordsWhere(CoreFilepoolProvider.FILES_TABLE, { stale: 1 }, where);
|
||||
await db.updateRecordsWhere(FILES_TABLE_NAME, { stale: 1 }, where);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2322,7 +2158,7 @@ export class CoreFilepoolProvider {
|
|||
|
||||
const db = await CoreSites.instance.getSiteDb(siteId);
|
||||
|
||||
await db.updateRecords(CoreFilepoolProvider.FILES_TABLE, { stale: 1 }, { fileId });
|
||||
await db.updateRecords(FILES_TABLE_NAME, { stale: 1 }, { fileId });
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2359,7 +2195,7 @@ export class CoreFilepoolProvider {
|
|||
whereAndParams[0] += ' AND (' + CoreFilepoolProvider.FILE_UPDATE_UNKNOWN_WHERE_CLAUSE + ')';
|
||||
}
|
||||
|
||||
await db.updateRecordsWhere(CoreFilepoolProvider.FILES_TABLE, { stale: 1 }, whereAndParams[0], whereAndParams[1]);
|
||||
await db.updateRecordsWhere(FILES_TABLE_NAME, { stale: 1 }, whereAndParams[0], whereAndParams[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2615,7 +2451,7 @@ export class CoreFilepoolProvider {
|
|||
|
||||
try {
|
||||
items = await this.appDB.getRecords<CoreFilepoolQueueEntry>(
|
||||
CoreFilepoolProvider.QUEUE_TABLE,
|
||||
QUEUE_TABLE_NAME,
|
||||
undefined,
|
||||
'priority DESC, added ASC',
|
||||
undefined,
|
||||
|
@ -2760,7 +2596,7 @@ export class CoreFilepoolProvider {
|
|||
protected async removeFromQueue(siteId: string, fileId: string): Promise<void> {
|
||||
await this.dbReady;
|
||||
|
||||
await this.appDB.deleteRecords(CoreFilepoolProvider.QUEUE_TABLE, { siteId, fileId });
|
||||
await this.appDB.deleteRecords(QUEUE_TABLE_NAME, { siteId, fileId });
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2797,10 +2633,10 @@ export class CoreFilepoolProvider {
|
|||
const promises: Promise<unknown>[] = [];
|
||||
|
||||
// Remove entry from filepool store.
|
||||
promises.push(db.deleteRecords(CoreFilepoolProvider.FILES_TABLE, conditions));
|
||||
promises.push(db.deleteRecords(FILES_TABLE_NAME, conditions));
|
||||
|
||||
// Remove links.
|
||||
promises.push(db.deleteRecords(CoreFilepoolProvider.LINKS_TABLE, conditions));
|
||||
promises.push(db.deleteRecords(LINKS_TABLE_NAME, conditions));
|
||||
|
||||
// Remove the file.
|
||||
if (CoreFile.instance.isAvailable()) {
|
||||
|
@ -2885,7 +2721,7 @@ export class CoreFilepoolProvider {
|
|||
const packageId = this.getPackageId(component, componentId);
|
||||
|
||||
// Get current stored data, we'll only update 'status' and 'updated' fields.
|
||||
const entry = <CoreFilepoolPackageEntry> site.getDb().getRecord(CoreFilepoolProvider.PACKAGES_TABLE, { id: packageId });
|
||||
const entry = <CoreFilepoolPackageEntry> site.getDb().getRecord(PACKAGES_TABLE_NAME, { id: packageId });
|
||||
const newData: CoreFilepoolPackageEntry = {};
|
||||
if (entry.status == CoreConstants.DOWNLOADING) {
|
||||
// Going back from downloading to previous status, restore previous download time.
|
||||
|
@ -2895,7 +2731,7 @@ export class CoreFilepoolProvider {
|
|||
newData.updated = Date.now();
|
||||
this.logger.debug(`Set previous status '${entry.status}' for package ${component} ${componentId}`);
|
||||
|
||||
await site.getDb().updateRecords(CoreFilepoolProvider.PACKAGES_TABLE, newData, { id: packageId });
|
||||
await site.getDb().updateRecords(PACKAGES_TABLE_NAME, newData, { id: packageId });
|
||||
// Success updating, trigger event.
|
||||
this.triggerPackageStatusChanged(site.id!, newData.status, component, componentId);
|
||||
|
||||
|
@ -2973,7 +2809,7 @@ export class CoreFilepoolProvider {
|
|||
let previousStatus: string | undefined;
|
||||
// Search current status to set it as previous status.
|
||||
try {
|
||||
const entry = <CoreFilepoolPackageEntry> site.getDb().getRecord(CoreFilepoolProvider.PACKAGES_TABLE, { id: packageId });
|
||||
const entry = <CoreFilepoolPackageEntry> site.getDb().getRecord(PACKAGES_TABLE_NAME, { id: packageId });
|
||||
if (typeof extra == 'undefined' || extra === null) {
|
||||
extra = entry.extra;
|
||||
}
|
||||
|
@ -3008,7 +2844,7 @@ export class CoreFilepoolProvider {
|
|||
return;
|
||||
}
|
||||
|
||||
await site.getDb().insertRecord(CoreFilepoolProvider.PACKAGES_TABLE, packageEntry);
|
||||
await site.getDb().insertRecord(PACKAGES_TABLE_NAME, packageEntry);
|
||||
|
||||
// Success inserting, trigger event.
|
||||
this.triggerPackageStatusChanged(siteId, status, component, componentId);
|
||||
|
@ -3132,7 +2968,7 @@ export class CoreFilepoolProvider {
|
|||
const packageId = this.getPackageId(component, componentId);
|
||||
|
||||
await site.getDb().updateRecords(
|
||||
CoreFilepoolProvider.PACKAGES_TABLE,
|
||||
PACKAGES_TABLE_NAME,
|
||||
{ downloadTime: CoreTimeUtils.instance.timestamp() },
|
||||
{ id: packageId },
|
||||
);
|
||||
|
@ -3142,166 +2978,6 @@ export class CoreFilepoolProvider {
|
|||
|
||||
export class CoreFilepool extends makeSingleton(CoreFilepoolProvider) {}
|
||||
|
||||
/**
|
||||
* File options.
|
||||
*/
|
||||
type CoreFilepoolFileOptions = {
|
||||
revision?: number; // File's revision.
|
||||
timemodified?: number; // File's timemodified.
|
||||
isexternalfile?: number; // 1 if it's a external file (from an external repository), 0 otherwise.
|
||||
repositorytype?: string; // Type of the repository this file belongs to.
|
||||
};
|
||||
|
||||
/**
|
||||
* Entry from filepool.
|
||||
*/
|
||||
export type CoreFilepoolFileEntry = CoreFilepoolFileOptions & {
|
||||
/**
|
||||
* The fileId to identify the file.
|
||||
*/
|
||||
fileId: string;
|
||||
|
||||
/**
|
||||
* File's URL.
|
||||
*/
|
||||
url: string;
|
||||
|
||||
/**
|
||||
* 1 if file is stale (needs to be updated), 0 otherwise.
|
||||
*/
|
||||
stale: number;
|
||||
|
||||
/**
|
||||
* Timestamp when this file was downloaded.
|
||||
*/
|
||||
downloadTime: number;
|
||||
|
||||
/**
|
||||
* File's path.
|
||||
*/
|
||||
path: string;
|
||||
|
||||
/**
|
||||
* File's extension.
|
||||
*/
|
||||
extension: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* DB data for entry from file's queue.
|
||||
*/
|
||||
export type CoreFilepoolQueueDBEntry = CoreFilepoolFileOptions & {
|
||||
/**
|
||||
* The site the file belongs to.
|
||||
*/
|
||||
siteId: string;
|
||||
|
||||
/**
|
||||
* The fileId to identify the file.
|
||||
*/
|
||||
fileId: string;
|
||||
|
||||
/**
|
||||
* Timestamp when the file was added to the queue.
|
||||
*/
|
||||
added: number;
|
||||
|
||||
/**
|
||||
* The priority of the file.
|
||||
*/
|
||||
priority: number;
|
||||
|
||||
/**
|
||||
* File's URL.
|
||||
*/
|
||||
url: string;
|
||||
|
||||
/**
|
||||
* File's path.
|
||||
*/
|
||||
path?: string;
|
||||
|
||||
/**
|
||||
* File links (to link the file to components and componentIds). Serialized to store on DB.
|
||||
*/
|
||||
links: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Entry from the file's queue.
|
||||
*/
|
||||
export type CoreFilepoolQueueEntry = CoreFilepoolQueueDBEntry & {
|
||||
/**
|
||||
* File links (to link the file to components and componentIds).
|
||||
*/
|
||||
linksUnserialized?: CoreFilepoolComponentLink[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Entry from packages table.
|
||||
*/
|
||||
export type CoreFilepoolPackageEntry = {
|
||||
/**
|
||||
* Package id.
|
||||
*/
|
||||
id?: string;
|
||||
|
||||
/**
|
||||
* The component to link the files to.
|
||||
*/
|
||||
component?: string;
|
||||
|
||||
/**
|
||||
* An ID to use in conjunction with the component.
|
||||
*/
|
||||
componentId?: string | number;
|
||||
|
||||
/**
|
||||
* Package status.
|
||||
*/
|
||||
status?: string;
|
||||
|
||||
/**
|
||||
* Package previous status.
|
||||
*/
|
||||
previous?: string;
|
||||
|
||||
/**
|
||||
* Timestamp when this package was updated.
|
||||
*/
|
||||
updated?: number;
|
||||
|
||||
/**
|
||||
* Timestamp when this package was downloaded.
|
||||
*/
|
||||
downloadTime?: number;
|
||||
|
||||
/**
|
||||
* Previous download time.
|
||||
*/
|
||||
previousDownloadTime?: number;
|
||||
|
||||
/**
|
||||
* Extra data stored by the package.
|
||||
*/
|
||||
extra?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* A component link.
|
||||
*/
|
||||
export type CoreFilepoolComponentLink = {
|
||||
/**
|
||||
* Link's component.
|
||||
*/
|
||||
component: string;
|
||||
|
||||
/**
|
||||
* Link's componentId.
|
||||
*/
|
||||
componentId?: string | number;
|
||||
};
|
||||
|
||||
/**
|
||||
* File actions.
|
||||
*/
|
||||
|
@ -3359,14 +3035,5 @@ type CoreFilepoolPromiseDefer = PromiseDefer<void> & {
|
|||
onProgress?: CoreFilepoolOnProgressCallback; // On Progress function.
|
||||
};
|
||||
|
||||
/**
|
||||
* Links table record type.
|
||||
*/
|
||||
type CoreFilepoolLinksRecord = {
|
||||
fileId: string; // File Id.
|
||||
component: string; // Component name.
|
||||
componentId: number | string; // Component Id.
|
||||
};
|
||||
|
||||
type AnchorOrMediaElement =
|
||||
HTMLAnchorElement | HTMLImageElement | HTMLAudioElement | HTMLVideoElement | HTMLSourceElement | HTMLTrackElement;
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { CoreAppSchema } from '@services/app';
|
||||
import { PromiseDefer } from '@services/utils/utils';
|
||||
|
||||
/**
|
||||
* Database variables for CoreLocalNotifications service.
|
||||
*/
|
||||
export const SITES_TABLE_NAME = 'notification_sites'; // Store to asigne unique codes to each site.
|
||||
export const COMPONENTS_TABLE_NAME = 'notification_components'; // Store to asigne unique codes to each component.
|
||||
export const TRIGGERED_TABLE_NAME = 'notifications_triggered'; // Store to prevent re-triggering notifications.
|
||||
export const APP_SCHEMA: CoreAppSchema = {
|
||||
name: 'CoreLocalNotificationsProvider',
|
||||
version: 1,
|
||||
tables: [
|
||||
{
|
||||
name: SITES_TABLE_NAME,
|
||||
columns: [
|
||||
{
|
||||
name: 'id',
|
||||
type: 'TEXT',
|
||||
primaryKey: true,
|
||||
},
|
||||
{
|
||||
name: 'code',
|
||||
type: 'INTEGER',
|
||||
notNull: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: COMPONENTS_TABLE_NAME,
|
||||
columns: [
|
||||
{
|
||||
name: 'id',
|
||||
type: 'TEXT',
|
||||
primaryKey: true,
|
||||
},
|
||||
{
|
||||
name: 'code',
|
||||
type: 'INTEGER',
|
||||
notNull: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: TRIGGERED_TABLE_NAME,
|
||||
columns: [
|
||||
{
|
||||
name: 'id',
|
||||
type: 'INTEGER',
|
||||
primaryKey: true,
|
||||
},
|
||||
{
|
||||
name: 'at',
|
||||
type: 'INTEGER',
|
||||
notNull: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export type CodeRequestsQueueItem = {
|
||||
table: string;
|
||||
id: string;
|
||||
deferreds: PromiseDefer<number>[];
|
||||
};
|
|
@ -16,11 +16,11 @@ import { Injectable } from '@angular/core';
|
|||
import { Subject, Subscription } from 'rxjs';
|
||||
import { ILocalNotification } from '@ionic-native/local-notifications';
|
||||
|
||||
import { CoreApp, CoreAppSchema } from '@services/app';
|
||||
import { CoreApp } from '@services/app';
|
||||
import { CoreConfig } from '@services/config';
|
||||
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
||||
import { CoreTextUtils } from '@services/utils/text';
|
||||
import { CoreUtils, PromiseDefer } from '@services/utils/utils';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { SQLiteDB } from '@classes/sqlitedb';
|
||||
import { CoreSite } from '@classes/site';
|
||||
import { CoreQueueRunner } from '@classes/queue-runner';
|
||||
|
@ -28,6 +28,13 @@ import { CoreError } from '@classes/errors/error';
|
|||
import { CoreConstants } from '@core/constants';
|
||||
import { makeSingleton, NgZone, Platform, Translate, LocalNotifications, Push, Device } from '@singletons/core.singletons';
|
||||
import { CoreLogger } from '@singletons/logger';
|
||||
import {
|
||||
APP_SCHEMA,
|
||||
TRIGGERED_TABLE_NAME,
|
||||
COMPONENTS_TABLE_NAME,
|
||||
SITES_TABLE_NAME,
|
||||
CodeRequestsQueueItem,
|
||||
} from '@services/local-notifications.db';
|
||||
|
||||
/**
|
||||
* Service to handle local notifications.
|
||||
|
@ -35,62 +42,6 @@ import { CoreLogger } from '@singletons/logger';
|
|||
@Injectable()
|
||||
export class CoreLocalNotificationsProvider {
|
||||
|
||||
// Variables for the database.
|
||||
protected static readonly SITES_TABLE = 'notification_sites'; // Store to asigne unique codes to each site.
|
||||
protected static readonly COMPONENTS_TABLE = 'notification_components'; // Store to asigne unique codes to each component.
|
||||
protected static readonly TRIGGERED_TABLE = 'notifications_triggered'; // Store to prevent re-triggering notifications.
|
||||
protected tablesSchema: CoreAppSchema = {
|
||||
name: 'CoreLocalNotificationsProvider',
|
||||
version: 1,
|
||||
tables: [
|
||||
{
|
||||
name: CoreLocalNotificationsProvider.SITES_TABLE,
|
||||
columns: [
|
||||
{
|
||||
name: 'id',
|
||||
type: 'TEXT',
|
||||
primaryKey: true,
|
||||
},
|
||||
{
|
||||
name: 'code',
|
||||
type: 'INTEGER',
|
||||
notNull: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: CoreLocalNotificationsProvider.COMPONENTS_TABLE,
|
||||
columns: [
|
||||
{
|
||||
name: 'id',
|
||||
type: 'TEXT',
|
||||
primaryKey: true,
|
||||
},
|
||||
{
|
||||
name: 'code',
|
||||
type: 'INTEGER',
|
||||
notNull: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: CoreLocalNotificationsProvider.TRIGGERED_TABLE,
|
||||
columns: [
|
||||
{
|
||||
name: 'id',
|
||||
type: 'INTEGER',
|
||||
primaryKey: true,
|
||||
},
|
||||
{
|
||||
name: 'at',
|
||||
type: 'INTEGER',
|
||||
notNull: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
protected logger: CoreLogger;
|
||||
protected appDB: SQLiteDB;
|
||||
protected dbReady: Promise<void>; // Promise resolved when the app DB is initialized.
|
||||
|
@ -111,7 +62,7 @@ export class CoreLocalNotificationsProvider {
|
|||
this.logger = CoreLogger.getInstance('CoreLocalNotificationsProvider');
|
||||
this.queueRunner = new CoreQueueRunner(10);
|
||||
this.appDB = CoreApp.instance.getDB();
|
||||
this.dbReady = CoreApp.instance.createTablesFromSchema(this.tablesSchema).catch(() => {
|
||||
this.dbReady = CoreApp.instance.createTablesFromSchema(APP_SCHEMA).catch(() => {
|
||||
// Ignore errors.
|
||||
});
|
||||
|
||||
|
@ -301,7 +252,7 @@ export class CoreLocalNotificationsProvider {
|
|||
* @return Promise resolved when the component code is retrieved.
|
||||
*/
|
||||
protected getComponentCode(component: string): Promise<number> {
|
||||
return this.requestCode(CoreLocalNotificationsProvider.COMPONENTS_TABLE, component);
|
||||
return this.requestCode(COMPONENTS_TABLE_NAME, component);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -312,7 +263,7 @@ export class CoreLocalNotificationsProvider {
|
|||
* @return Promise resolved when the site code is retrieved.
|
||||
*/
|
||||
protected getSiteCode(siteId: string): Promise<number> {
|
||||
return this.requestCode(CoreLocalNotificationsProvider.SITES_TABLE, siteId);
|
||||
return this.requestCode(SITES_TABLE_NAME, siteId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -377,7 +328,7 @@ export class CoreLocalNotificationsProvider {
|
|||
|
||||
try {
|
||||
const stored = await this.appDB.getRecord<{ id: number; at: number }>(
|
||||
CoreLocalNotificationsProvider.TRIGGERED_TABLE,
|
||||
TRIGGERED_TABLE_NAME,
|
||||
{ id: notification.id },
|
||||
);
|
||||
|
||||
|
@ -532,7 +483,7 @@ export class CoreLocalNotificationsProvider {
|
|||
async removeTriggered(id: number): Promise<void> {
|
||||
await this.dbReady;
|
||||
|
||||
await this.appDB.deleteRecords(CoreLocalNotificationsProvider.TRIGGERED_TABLE, { id: id });
|
||||
await this.appDB.deleteRecords(TRIGGERED_TABLE_NAME, { id: id });
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -695,7 +646,7 @@ export class CoreLocalNotificationsProvider {
|
|||
at: notification.trigger && notification.trigger.at ? notification.trigger.at.getTime() : Date.now(),
|
||||
};
|
||||
|
||||
return this.appDB.insertRecord(CoreLocalNotificationsProvider.TRIGGERED_TABLE, entry);
|
||||
return this.appDB.insertRecord(TRIGGERED_TABLE_NAME, entry);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -708,10 +659,10 @@ export class CoreLocalNotificationsProvider {
|
|||
async updateComponentName(oldName: string, newName: string): Promise<void> {
|
||||
await this.dbReady;
|
||||
|
||||
const oldId = CoreLocalNotificationsProvider.COMPONENTS_TABLE + '#' + oldName;
|
||||
const newId = CoreLocalNotificationsProvider.COMPONENTS_TABLE + '#' + newName;
|
||||
const oldId = COMPONENTS_TABLE_NAME + '#' + oldName;
|
||||
const newId = COMPONENTS_TABLE_NAME + '#' + newName;
|
||||
|
||||
await this.appDB.updateRecords(CoreLocalNotificationsProvider.COMPONENTS_TABLE, { id: newId }, { id: oldId });
|
||||
await this.appDB.updateRecords(COMPONENTS_TABLE_NAME, { id: newId }, { id: oldId });
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -719,9 +670,3 @@ export class CoreLocalNotificationsProvider {
|
|||
export class CoreLocalNotifications extends makeSingleton(CoreLocalNotificationsProvider) {}
|
||||
|
||||
export type CoreLocalNotificationsClickCallback<T = unknown> = (value: T) => void;
|
||||
|
||||
type CodeRequestsQueueItem = {
|
||||
table: string;
|
||||
id: string;
|
||||
deferreds: PromiseDefer<number>[];
|
||||
};
|
||||
|
|
|
@ -0,0 +1,233 @@
|
|||
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { CoreAppSchema } from '@services/app';
|
||||
import { CoreSiteSchema, registerSiteSchema } from '@services/sites';
|
||||
import { SQLiteDB, SQLiteDBTableSchema } from '@classes/sqlitedb';
|
||||
import { CoreSite } from '@classes/site';
|
||||
|
||||
/**
|
||||
* Database variables for CoreSites service.
|
||||
*/
|
||||
export const SITES_TABLE_NAME = 'sites_2';
|
||||
export const CURRENT_SITE_TABLE_NAME = 'current_site';
|
||||
export const SCHEMA_VERSIONS_TABLE_NAME = 'schema_versions';
|
||||
|
||||
// Schema to register in App DB.
|
||||
export const APP_SCHEMA: CoreAppSchema = {
|
||||
name: 'CoreSitesProvider',
|
||||
version: 2,
|
||||
tables: [
|
||||
{
|
||||
name: SITES_TABLE_NAME,
|
||||
columns: [
|
||||
{
|
||||
name: 'id',
|
||||
type: 'TEXT',
|
||||
primaryKey: true,
|
||||
},
|
||||
{
|
||||
name: 'siteUrl',
|
||||
type: 'TEXT',
|
||||
notNull: true,
|
||||
},
|
||||
{
|
||||
name: 'token',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'info',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'privateToken',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'config',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'loggedOut',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'oauthId',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: CURRENT_SITE_TABLE_NAME,
|
||||
columns: [
|
||||
{
|
||||
name: 'id',
|
||||
type: 'INTEGER',
|
||||
primaryKey: true,
|
||||
},
|
||||
{
|
||||
name: 'siteId',
|
||||
type: 'TEXT',
|
||||
notNull: true,
|
||||
unique: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
async migrate(db: SQLiteDB, oldVersion: number): Promise<void> {
|
||||
if (oldVersion < 2) {
|
||||
const newTable = SITES_TABLE_NAME;
|
||||
const oldTable = 'sites';
|
||||
|
||||
try {
|
||||
// Check if V1 table exists.
|
||||
await db.tableExists(oldTable);
|
||||
|
||||
// Move the records from the old table.
|
||||
const sites = await db.getAllRecords<SiteDBEntry>(oldTable);
|
||||
const promises: Promise<number>[] = [];
|
||||
|
||||
sites.forEach((site) => {
|
||||
promises.push(db.insertRecord(newTable, site));
|
||||
});
|
||||
|
||||
await Promise.all(promises);
|
||||
|
||||
// Data moved, drop the old table.
|
||||
await db.dropTable(oldTable);
|
||||
} catch (error) {
|
||||
// Old table does not exist, ignore.
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// Schema to register for Site DB.
|
||||
export const SITE_SCHEMA: CoreSiteSchema = {
|
||||
name: 'CoreSitesProvider',
|
||||
version: 2,
|
||||
canBeCleared: [CoreSite.WS_CACHE_TABLE],
|
||||
tables: [
|
||||
{
|
||||
name: CoreSite.WS_CACHE_TABLE,
|
||||
columns: [
|
||||
{
|
||||
name: 'id',
|
||||
type: 'TEXT',
|
||||
primaryKey: true,
|
||||
},
|
||||
{
|
||||
name: 'data',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'key',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'expirationTime',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'component',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'componentId',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: CoreSite.CONFIG_TABLE,
|
||||
columns: [
|
||||
{
|
||||
name: 'name',
|
||||
type: 'TEXT',
|
||||
unique: true,
|
||||
notNull: true,
|
||||
},
|
||||
{
|
||||
name: 'value',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
async migrate(db: SQLiteDB, oldVersion: number): Promise<void> {
|
||||
if (oldVersion && oldVersion < 2) {
|
||||
const newTable = CoreSite.WS_CACHE_TABLE;
|
||||
const oldTable = 'wscache';
|
||||
|
||||
try {
|
||||
await db.tableExists(oldTable);
|
||||
} catch (error) {
|
||||
// Old table does not exist, ignore.
|
||||
return;
|
||||
}
|
||||
// Cannot use insertRecordsFrom because there are extra fields, so manually code INSERT INTO.
|
||||
await db.execute(
|
||||
'INSERT INTO ' + newTable + ' ' +
|
||||
'SELECT id, data, key, expirationTime, NULL as component, NULL as componentId ' +
|
||||
'FROM ' + oldTable,
|
||||
);
|
||||
|
||||
try {
|
||||
await db.dropTable(oldTable);
|
||||
} catch (error) {
|
||||
// Error deleting old table, ignore.
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// Table for site DB to include the schema versions. It's not part of SITE_SCHEMA because it needs to be created first.
|
||||
export const SCHEMA_VERSIONS_TABLE_SCHEMA: SQLiteDBTableSchema = {
|
||||
name: SCHEMA_VERSIONS_TABLE_NAME,
|
||||
columns: [
|
||||
{
|
||||
name: 'name',
|
||||
type: 'TEXT',
|
||||
primaryKey: true,
|
||||
},
|
||||
{
|
||||
name: 'version',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export type SiteDBEntry = {
|
||||
id: string;
|
||||
siteUrl: string;
|
||||
token: string;
|
||||
info: string;
|
||||
privateToken: string;
|
||||
config: string;
|
||||
loggedOut: number;
|
||||
oauthId: number;
|
||||
};
|
||||
|
||||
export type CurrentSiteDBEntry = {
|
||||
id: number;
|
||||
siteId: string;
|
||||
};
|
||||
|
||||
export type SchemaVersionsDBEntry = {
|
||||
name: string;
|
||||
version: number;
|
||||
};
|
||||
|
||||
export const initCoreSitesDB = (): void => {
|
||||
registerSiteSchema(SITE_SCHEMA);
|
||||
};
|
|
@ -16,7 +16,7 @@ import { Injectable } from '@angular/core';
|
|||
import { Md5 } from 'ts-md5/dist/md5';
|
||||
import { timeout } from 'rxjs/operators';
|
||||
|
||||
import { CoreApp, CoreAppSchema, CoreStoreConfig } from '@services/app';
|
||||
import { CoreApp, CoreStoreConfig } from '@services/app';
|
||||
import { CoreEvents } from '@singletons/events';
|
||||
import { CoreWS } from '@services/ws';
|
||||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
|
@ -38,114 +38,36 @@ import { CoreError } from '@classes/errors/error';
|
|||
import { CoreSiteError } from '@classes/errors/siteerror';
|
||||
import { makeSingleton, Translate, Http } from '@singletons/core.singletons';
|
||||
import { CoreLogger } from '@singletons/logger';
|
||||
import {
|
||||
APP_SCHEMA,
|
||||
SCHEMA_VERSIONS_TABLE_SCHEMA,
|
||||
SITES_TABLE_NAME,
|
||||
CURRENT_SITE_TABLE_NAME,
|
||||
SCHEMA_VERSIONS_TABLE_NAME,
|
||||
SiteDBEntry,
|
||||
CurrentSiteDBEntry,
|
||||
SchemaVersionsDBEntry,
|
||||
} from '@services/sites.db';
|
||||
|
||||
const SITES_TABLE = 'sites_2';
|
||||
const CURRENT_SITE_TABLE = 'current_site';
|
||||
const SCHEMA_VERSIONS_TABLE = 'schema_versions';
|
||||
|
||||
// Schemas for site tables. Other providers can add schemas in here using the registerSiteSchema function.
|
||||
const siteSchemas: { [name: string]: CoreRegisteredSiteSchema } = {};
|
||||
export const registerSiteSchema = (schema: CoreSiteSchema): void => {
|
||||
siteSchemas[schema.name] = schema;
|
||||
};
|
||||
|
||||
/*
|
||||
* Service to manage and interact with sites.
|
||||
* It allows creating tables in the databases of all sites. Each service or component should be responsible of creating
|
||||
* their own database tables. Example:
|
||||
*
|
||||
* constructor(sitesProvider: CoreSitesProvider) {
|
||||
* this.sitesProvider.registerSiteSchema(this.tableSchema);
|
||||
* import { registerSiteSchema } from '@services/sites';
|
||||
*
|
||||
* This provider will automatically create the tables in the databases of all the instantiated sites, and also to the
|
||||
* databases of sites instantiated from now on.
|
||||
* registerSiteSchema(tableSchema);
|
||||
*/
|
||||
@Injectable()
|
||||
export class CoreSitesProvider {
|
||||
|
||||
// Variables for the database.
|
||||
protected appTablesSchema: CoreAppSchema = {
|
||||
name: 'CoreSitesProvider',
|
||||
version: 2,
|
||||
tables: [
|
||||
{
|
||||
name: SITES_TABLE,
|
||||
columns: [
|
||||
{
|
||||
name: 'id',
|
||||
type: 'TEXT',
|
||||
primaryKey: true,
|
||||
},
|
||||
{
|
||||
name: 'siteUrl',
|
||||
type: 'TEXT',
|
||||
notNull: true,
|
||||
},
|
||||
{
|
||||
name: 'token',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'info',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'privateToken',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'config',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'loggedOut',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'oauthId',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: CURRENT_SITE_TABLE,
|
||||
columns: [
|
||||
{
|
||||
name: 'id',
|
||||
type: 'INTEGER',
|
||||
primaryKey: true,
|
||||
},
|
||||
{
|
||||
name: 'siteId',
|
||||
type: 'TEXT',
|
||||
notNull: true,
|
||||
unique: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
async migrate(db: SQLiteDB, oldVersion: number): Promise<void> {
|
||||
if (oldVersion < 2) {
|
||||
const newTable = SITES_TABLE;
|
||||
const oldTable = 'sites';
|
||||
|
||||
try {
|
||||
// Check if V1 table exists.
|
||||
await db.tableExists(oldTable);
|
||||
|
||||
// Move the records from the old table.
|
||||
const sites = await db.getAllRecords<SiteDBEntry>(oldTable);
|
||||
const promises: Promise<number>[] = [];
|
||||
|
||||
sites.forEach((site) => {
|
||||
promises.push(db.insertRecord(newTable, site));
|
||||
});
|
||||
|
||||
await Promise.all(promises);
|
||||
|
||||
// Data moved, drop the old table.
|
||||
await db.dropTable(oldTable);
|
||||
} catch (error) {
|
||||
// Old table does not exist, ignore.
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// Constants to validate a site version.
|
||||
protected readonly WORKPLACE_APP = 3;
|
||||
protected readonly MOODLE_APP = 2;
|
||||
|
@ -162,112 +84,15 @@ export class CoreSitesProvider {
|
|||
protected appDB: SQLiteDB;
|
||||
protected dbReady: Promise<void>; // Promise resolved when the app DB is initialized.
|
||||
protected siteSchemasMigration: { [siteId: string]: Promise<void> } = {};
|
||||
|
||||
// Schemas for site tables. Other providers can add schemas in here.
|
||||
protected siteSchemas: { [name: string]: CoreRegisteredSiteSchema } = {};
|
||||
protected siteTablesSchemas: SQLiteDBTableSchema[] = [
|
||||
{
|
||||
name: SCHEMA_VERSIONS_TABLE,
|
||||
columns: [
|
||||
{
|
||||
name: 'name',
|
||||
type: 'TEXT',
|
||||
primaryKey: true,
|
||||
},
|
||||
{
|
||||
name: 'version',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
// Site schema for this provider.
|
||||
protected siteSchema: CoreSiteSchema = {
|
||||
name: 'CoreSitesProvider',
|
||||
version: 2,
|
||||
canBeCleared: [CoreSite.WS_CACHE_TABLE],
|
||||
tables: [
|
||||
{
|
||||
name: CoreSite.WS_CACHE_TABLE,
|
||||
columns: [
|
||||
{
|
||||
name: 'id',
|
||||
type: 'TEXT',
|
||||
primaryKey: true,
|
||||
},
|
||||
{
|
||||
name: 'data',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'key',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'expirationTime',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'component',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'componentId',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: CoreSite.CONFIG_TABLE,
|
||||
columns: [
|
||||
{
|
||||
name: 'name',
|
||||
type: 'TEXT',
|
||||
unique: true,
|
||||
notNull: true,
|
||||
},
|
||||
{
|
||||
name: 'value',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
async migrate(db: SQLiteDB, oldVersion: number): Promise<void> {
|
||||
if (oldVersion && oldVersion < 2) {
|
||||
const newTable = CoreSite.WS_CACHE_TABLE;
|
||||
const oldTable = 'wscache';
|
||||
|
||||
try {
|
||||
await db.tableExists(oldTable);
|
||||
} catch (error) {
|
||||
// Old table does not exist, ignore.
|
||||
return;
|
||||
}
|
||||
// Cannot use insertRecordsFrom because there are extra fields, so manually code INSERT INTO.
|
||||
await db.execute(
|
||||
'INSERT INTO ' + newTable + ' ' +
|
||||
'SELECT id, data, key, expirationTime, NULL as component, NULL as componentId ' +
|
||||
'FROM ' + oldTable,
|
||||
);
|
||||
|
||||
try {
|
||||
await db.dropTable(oldTable);
|
||||
} catch (error) {
|
||||
// Error deleting old table, ignore.
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
protected pluginsSiteSchemas: { [name: string]: CoreRegisteredSiteSchema } = {};
|
||||
|
||||
constructor() {
|
||||
this.logger = CoreLogger.getInstance('CoreSitesProvider');
|
||||
|
||||
this.appDB = CoreApp.instance.getDB();
|
||||
this.dbReady = CoreApp.instance.createTablesFromSchema(this.appTablesSchema).catch(() => {
|
||||
this.dbReady = CoreApp.instance.createTablesFromSchema(APP_SCHEMA).catch(() => {
|
||||
// Ignore errors.
|
||||
});
|
||||
this.registerSiteSchema(this.siteSchema);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -857,7 +682,7 @@ export class CoreSitesProvider {
|
|||
oauthId,
|
||||
};
|
||||
|
||||
await this.appDB.insertRecord(SITES_TABLE, entry);
|
||||
await this.appDB.insertRecord(SITES_TABLE_NAME, entry);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1084,7 +909,7 @@ export class CoreSitesProvider {
|
|||
delete this.sites[siteId];
|
||||
|
||||
try {
|
||||
await this.appDB.deleteRecords(SITES_TABLE, { id: siteId });
|
||||
await this.appDB.deleteRecords(SITES_TABLE_NAME, { id: siteId });
|
||||
} catch (err) {
|
||||
// DB remove shouldn't fail, but we'll go ahead even if it does.
|
||||
}
|
||||
|
@ -1103,7 +928,7 @@ export class CoreSitesProvider {
|
|||
async hasSites(): Promise<boolean> {
|
||||
await this.dbReady;
|
||||
|
||||
const count = await this.appDB.countRecords(SITES_TABLE);
|
||||
const count = await this.appDB.countRecords(SITES_TABLE_NAME);
|
||||
|
||||
return count > 0;
|
||||
}
|
||||
|
@ -1129,7 +954,7 @@ export class CoreSitesProvider {
|
|||
return this.sites[siteId];
|
||||
} else {
|
||||
// Retrieve and create the site.
|
||||
const data = await this.appDB.getRecord<SiteDBEntry>(SITES_TABLE, { id: siteId });
|
||||
const data = await this.appDB.getRecord<SiteDBEntry>(SITES_TABLE_NAME, { id: siteId });
|
||||
|
||||
return this.makeSiteFromSiteListEntry(data);
|
||||
}
|
||||
|
@ -1202,7 +1027,7 @@ export class CoreSitesProvider {
|
|||
async getSites(ids?: string[]): Promise<CoreSiteBasicInfo[]> {
|
||||
await this.dbReady;
|
||||
|
||||
const sites = await this.appDB.getAllRecords<SiteDBEntry>(SITES_TABLE);
|
||||
const sites = await this.appDB.getAllRecords<SiteDBEntry>(SITES_TABLE_NAME);
|
||||
|
||||
const formattedSites: CoreSiteBasicInfo[] = [];
|
||||
sites.forEach((site) => {
|
||||
|
@ -1266,7 +1091,7 @@ export class CoreSitesProvider {
|
|||
async getLoggedInSitesIds(): Promise<string[]> {
|
||||
await this.dbReady;
|
||||
|
||||
const sites = await this.appDB.getRecords<SiteDBEntry>(SITES_TABLE, { loggedOut : 0 });
|
||||
const sites = await this.appDB.getRecords<SiteDBEntry>(SITES_TABLE_NAME, { loggedOut : 0 });
|
||||
|
||||
return sites.map((site) => site.id);
|
||||
}
|
||||
|
@ -1279,7 +1104,7 @@ export class CoreSitesProvider {
|
|||
async getSitesIds(): Promise<string[]> {
|
||||
await this.dbReady;
|
||||
|
||||
const sites = await this.appDB.getAllRecords<SiteDBEntry>(SITES_TABLE);
|
||||
const sites = await this.appDB.getAllRecords<SiteDBEntry>(SITES_TABLE_NAME);
|
||||
|
||||
return sites.map((site) => site.id);
|
||||
}
|
||||
|
@ -1298,7 +1123,7 @@ export class CoreSitesProvider {
|
|||
siteId,
|
||||
};
|
||||
|
||||
await this.appDB.insertRecord(CURRENT_SITE_TABLE, entry);
|
||||
await this.appDB.insertRecord(CURRENT_SITE_TABLE_NAME, entry);
|
||||
|
||||
CoreEvents.trigger(CoreEvents.LOGIN, {}, siteId);
|
||||
}
|
||||
|
@ -1324,7 +1149,7 @@ export class CoreSitesProvider {
|
|||
promises.push(this.setSiteLoggedOut(siteId, true));
|
||||
}
|
||||
|
||||
promises.push(this.appDB.deleteRecords(CURRENT_SITE_TABLE, { id: 1 }));
|
||||
promises.push(this.appDB.deleteRecords(CURRENT_SITE_TABLE_NAME, { id: 1 }));
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -1349,7 +1174,7 @@ export class CoreSitesProvider {
|
|||
this.sessionRestored = true;
|
||||
|
||||
try {
|
||||
const currentSite = await this.appDB.getRecord<CurrentSiteDBEntry>(CURRENT_SITE_TABLE, { id: 1 });
|
||||
const currentSite = await this.appDB.getRecord<CurrentSiteDBEntry>(CURRENT_SITE_TABLE_NAME, { id: 1 });
|
||||
const siteId = currentSite.siteId;
|
||||
this.logger.debug(`Restore session in site ${siteId}`);
|
||||
|
||||
|
@ -1377,7 +1202,7 @@ export class CoreSitesProvider {
|
|||
|
||||
site.setLoggedOut(loggedOut);
|
||||
|
||||
await this.appDB.updateRecords(SITES_TABLE, newValues, { id: siteId });
|
||||
await this.appDB.updateRecords(SITES_TABLE_NAME, newValues, { id: siteId });
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1426,7 +1251,7 @@ export class CoreSitesProvider {
|
|||
site.privateToken = privateToken;
|
||||
site.setLoggedOut(false); // Token updated means the user authenticated again, not logged out anymore.
|
||||
|
||||
await this.appDB.updateRecords(SITES_TABLE, newValues, { id: siteId });
|
||||
await this.appDB.updateRecords(SITES_TABLE_NAME, newValues, { id: siteId });
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1470,7 +1295,7 @@ export class CoreSitesProvider {
|
|||
}
|
||||
|
||||
try {
|
||||
await this.appDB.updateRecords(SITES_TABLE, newValues, { id: siteId });
|
||||
await this.appDB.updateRecords(SITES_TABLE_NAME, newValues, { id: siteId });
|
||||
} finally {
|
||||
CoreEvents.trigger(CoreEvents.SITE_UPDATED, info, siteId);
|
||||
}
|
||||
|
@ -1529,7 +1354,7 @@ export class CoreSitesProvider {
|
|||
}
|
||||
|
||||
try {
|
||||
const siteEntries = await this.appDB.getAllRecords<SiteDBEntry>(SITES_TABLE);
|
||||
const siteEntries = await this.appDB.getAllRecords<SiteDBEntry>(SITES_TABLE_NAME);
|
||||
const ids: string[] = [];
|
||||
const promises: Promise<unknown>[] = [];
|
||||
|
||||
|
@ -1562,7 +1387,7 @@ export class CoreSitesProvider {
|
|||
async getStoredCurrentSiteId(): Promise<string> {
|
||||
await this.dbReady;
|
||||
|
||||
const currentSite = await this.appDB.getRecord<CurrentSiteDBEntry>(CURRENT_SITE_TABLE, { id: 1 });
|
||||
const currentSite = await this.appDB.getRecord<CurrentSiteDBEntry>(CURRENT_SITE_TABLE_NAME, { id: 1 });
|
||||
|
||||
return currentSite.siteId;
|
||||
}
|
||||
|
@ -1605,32 +1430,6 @@ export class CoreSitesProvider {
|
|||
return this.getSite(siteId).then((site) => site.isFeatureDisabled(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a table in all the sites databases.
|
||||
*
|
||||
* @param table Table schema.
|
||||
* @deprecated. Please use registerSiteSchema instead.
|
||||
*/
|
||||
createTableFromSchema(table: SQLiteDBTableSchema): void {
|
||||
this.createTablesFromSchema([table]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create several tables in all the sites databases.
|
||||
*
|
||||
* @param tables List of tables schema.
|
||||
* @deprecated. Please use registerSiteSchema instead.
|
||||
*/
|
||||
createTablesFromSchema(tables: SQLiteDBTableSchema[]): void {
|
||||
// Add the tables to the list of schemas. This list is to create all the tables in new sites.
|
||||
this.siteTablesSchemas = this.siteTablesSchemas.concat(tables);
|
||||
|
||||
// Now create these tables in current sites.
|
||||
for (const id in this.sites) {
|
||||
this.sites[id].getDb().createTablesFromSchema(tables);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a WS is available in the current site, if any.
|
||||
*
|
||||
|
@ -1645,40 +1444,29 @@ export class CoreSitesProvider {
|
|||
}
|
||||
|
||||
/**
|
||||
* Register a site schema.
|
||||
* Register a site schema in current site.
|
||||
* This function is meant for site plugins to create DB tables in current site. Tables created from within the app
|
||||
* whould use the registerSiteSchema function exported in this same file.
|
||||
*
|
||||
* @param schema The schema to register.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
async registerSiteSchema(schema: CoreSiteSchema): Promise<void> {
|
||||
if (this.currentSite) {
|
||||
try {
|
||||
// Site has already been created, apply the schema directly.
|
||||
const schemas: {[name: string]: CoreRegisteredSiteSchema} = {};
|
||||
schemas[schema.name] = schema;
|
||||
if (!this.currentSite) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!schema.onlyCurrentSite) {
|
||||
// Apply it to all sites.
|
||||
const siteIds = await this.getSitesIds();
|
||||
try {
|
||||
// Site has already been created, apply the schema directly.
|
||||
const schemas: {[name: string]: CoreRegisteredSiteSchema} = {};
|
||||
schemas[schema.name] = schema;
|
||||
|
||||
await Promise.all(siteIds.map(async (siteId) => {
|
||||
const site = await this.getSite(siteId);
|
||||
// Apply it to the specified site only.
|
||||
(schema as CoreRegisteredSiteSchema).siteId = this.currentSite.getId();
|
||||
|
||||
return this.applySiteSchemas(site, schemas);
|
||||
}));
|
||||
} else {
|
||||
// Apply it to the specified site only.
|
||||
(schema as CoreRegisteredSiteSchema).siteId = this.currentSite.getId();
|
||||
|
||||
await this.applySiteSchemas(this.currentSite, schemas);
|
||||
}
|
||||
} finally {
|
||||
// Add the schema to the list. It's done in the end to prevent a schema being applied twice.
|
||||
this.siteSchemas[schema.name] = schema;
|
||||
}
|
||||
} else if (!schema.onlyCurrentSite) {
|
||||
// Add the schema to the list, it will be applied when the sites are created.
|
||||
this.siteSchemas[schema.name] = schema;
|
||||
await this.applySiteSchemas(this.currentSite, schemas);
|
||||
} finally {
|
||||
this.pluginsSiteSchemas[schema.name] = schema;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1700,8 +1488,8 @@ export class CoreSitesProvider {
|
|||
this.logger.debug(`Migrating all schemas of ${site.id}`);
|
||||
|
||||
// First create tables not registerd with name/version.
|
||||
const promise = site.getDb().createTablesFromSchema(this.siteTablesSchemas)
|
||||
.then(() => this.applySiteSchemas(site, this.siteSchemas));
|
||||
const promise = site.getDb().createTableFromSchema(SCHEMA_VERSIONS_TABLE_SCHEMA)
|
||||
.then(() => this.applySiteSchemas(site, siteSchemas));
|
||||
|
||||
this.siteSchemasMigration[site.id] = promise;
|
||||
|
||||
|
@ -1721,7 +1509,7 @@ export class CoreSitesProvider {
|
|||
const db = site.getDb();
|
||||
|
||||
// Fetch installed versions of the schema.
|
||||
const records = await db.getAllRecords<SchemaVersionsDBEntry>(SCHEMA_VERSIONS_TABLE);
|
||||
const records = await db.getAllRecords<SchemaVersionsDBEntry>(SCHEMA_VERSIONS_TABLE_NAME);
|
||||
|
||||
const versions: {[name: string]: number} = {};
|
||||
records.forEach((record) => {
|
||||
|
@ -1768,7 +1556,7 @@ export class CoreSitesProvider {
|
|||
}
|
||||
|
||||
// Set installed version.
|
||||
await db.insertRecord(SCHEMA_VERSIONS_TABLE, { name, version: schema.version });
|
||||
await db.insertRecord(SCHEMA_VERSIONS_TABLE_NAME, { name, version: schema.version });
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1814,13 +1602,13 @@ export class CoreSitesProvider {
|
|||
*/
|
||||
getSiteTableSchemasToClear(site: CoreSite): string[] {
|
||||
let reset: string[] = [];
|
||||
for (const name in this.siteSchemas) {
|
||||
const schema = this.siteSchemas[name];
|
||||
const schemas = Object.values(siteSchemas).concat(Object.values(this.pluginsSiteSchemas));
|
||||
|
||||
schemas.forEach((schema) => {
|
||||
if (schema.canBeCleared && (!schema.siteId || site.getId() == schema.siteId)) {
|
||||
reset = reset.concat(schema.canBeCleared);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return reset;
|
||||
}
|
||||
|
@ -1980,12 +1768,6 @@ export type CoreSiteSchema = {
|
|||
*/
|
||||
canBeCleared?: string[];
|
||||
|
||||
/**
|
||||
* If true, the schema will only be applied to the current site. Otherwise it will be applied to all sites.
|
||||
* If you're implementing a site plugin, please set it to true.
|
||||
*/
|
||||
onlyCurrentSite?: boolean;
|
||||
|
||||
/**
|
||||
* Tables to create when installing or upgrading the schema.
|
||||
*/
|
||||
|
@ -2088,24 +1870,3 @@ export type CoreSitesLoginTokenResponse = {
|
|||
debuginfo?: string;
|
||||
reproductionlink?: string;
|
||||
};
|
||||
|
||||
type SiteDBEntry = {
|
||||
id: string;
|
||||
siteUrl: string;
|
||||
token: string;
|
||||
info: string;
|
||||
privateToken: string;
|
||||
config: string;
|
||||
loggedOut: number;
|
||||
oauthId: number;
|
||||
};
|
||||
|
||||
type CurrentSiteDBEntry = {
|
||||
id: number;
|
||||
siteId: string;
|
||||
};
|
||||
|
||||
type SchemaVersionsDBEntry = {
|
||||
name: string;
|
||||
version: number;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { CoreSiteSchema, registerSiteSchema } from '@services/sites';
|
||||
|
||||
/**
|
||||
* Database variables for CoreSync service.
|
||||
*/
|
||||
export const SYNC_TABLE_NAME = 'sync';
|
||||
export const SITE_SCHEMA: CoreSiteSchema = {
|
||||
name: 'CoreSyncProvider',
|
||||
version: 1,
|
||||
tables: [
|
||||
{
|
||||
name: SYNC_TABLE_NAME,
|
||||
columns: [
|
||||
{
|
||||
name: 'component',
|
||||
type: 'TEXT',
|
||||
notNull: true,
|
||||
},
|
||||
{
|
||||
name: 'id',
|
||||
type: 'TEXT',
|
||||
notNull: true,
|
||||
},
|
||||
{
|
||||
name: 'time',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'warnings',
|
||||
type: 'TEXT',
|
||||
},
|
||||
],
|
||||
primaryKeys: ['component', 'id'],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export type CoreSyncRecord = {
|
||||
component: string;
|
||||
id: string;
|
||||
time: number;
|
||||
warnings: string;
|
||||
};
|
||||
|
||||
export const initCoreSyncDB = (): void => {
|
||||
registerSiteSchema(SITE_SCHEMA);
|
||||
};
|
||||
|
|
@ -16,8 +16,7 @@ import { Injectable } from '@angular/core';
|
|||
import { CoreEvents } from '@singletons/events';
|
||||
import { CoreSites, CoreSiteSchema } from '@services/sites';
|
||||
import { makeSingleton } from '@singletons/core.singletons';
|
||||
|
||||
const SYNC_TABLE = 'sync';
|
||||
import { SYNC_TABLE_NAME, CoreSyncRecord } from '@services/sync.db';
|
||||
|
||||
/*
|
||||
* Service that provides some features regarding synchronization.
|
||||
|
@ -31,7 +30,7 @@ export class CoreSyncProvider {
|
|||
version: 1,
|
||||
tables: [
|
||||
{
|
||||
name: SYNC_TABLE,
|
||||
name: SYNC_TABLE_NAME,
|
||||
columns: [
|
||||
{
|
||||
name: 'component',
|
||||
|
@ -61,8 +60,6 @@ export class CoreSyncProvider {
|
|||
protected blockedItems: { [siteId: string]: { [blockId: string]: { [operation: string]: boolean } } } = {};
|
||||
|
||||
constructor() {
|
||||
CoreSites.instance.registerSiteSchema(this.siteSchema);
|
||||
|
||||
// Unblock all blocks on logout.
|
||||
CoreEvents.on(CoreEvents.LOGOUT, (data: {siteId: string}) => {
|
||||
this.clearAllBlocks(data.siteId);
|
||||
|
@ -133,7 +130,7 @@ export class CoreSyncProvider {
|
|||
* @return Record if found or reject.
|
||||
*/
|
||||
getSyncRecord(component: string, id: string | number, siteId?: string): Promise<CoreSyncRecord> {
|
||||
return CoreSites.instance.getSiteDb(siteId).then((db) => db.getRecord(SYNC_TABLE, { component: component, id: id }));
|
||||
return CoreSites.instance.getSiteDb(siteId).then((db) => db.getRecord(SYNC_TABLE_NAME, { component: component, id: id }));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -151,7 +148,7 @@ export class CoreSyncProvider {
|
|||
data.component = component;
|
||||
data.id = id;
|
||||
|
||||
await db.insertRecord(SYNC_TABLE, data);
|
||||
await db.insertRecord(SYNC_TABLE_NAME, data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -211,10 +208,3 @@ export class CoreSyncProvider {
|
|||
}
|
||||
|
||||
export class CoreSync extends makeSingleton(CoreSyncProvider) {}
|
||||
|
||||
export type CoreSyncRecord = {
|
||||
component: string;
|
||||
id: string;
|
||||
time: number;
|
||||
warnings: string;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue