forked from CIT/Vmeda.Online
177 lines
6.9 KiB
TypeScript
177 lines
6.9 KiB
TypeScript
// (C) Copyright 2015 Martin Dougiamas
|
||
//
|
||
// 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 { Injectable } from '@angular/core';
|
||
import { CoreConfigProvider } from './config';
|
||
import { CoreFilepoolProvider } from './filepool';
|
||
import { CoreInitHandler, CoreInitDelegate } from './init';
|
||
import { CoreLocalNotificationsProvider } from './local-notifications';
|
||
import { CoreLoggerProvider } from './logger';
|
||
import { CoreSitesProvider } from './sites';
|
||
import { CoreConfigConstants } from '../configconstants';
|
||
|
||
/**
|
||
* Factory to handle app updates. This factory shouldn't be used outside of core.
|
||
*
|
||
* This service handles processes that need to be run when updating the app, like migrate Ionic 1 database data to Ionic 3.
|
||
*/
|
||
@Injectable()
|
||
export class CoreUpdateManagerProvider implements CoreInitHandler {
|
||
// Data for init delegate.
|
||
public name = 'CoreUpdateManager';
|
||
public priority = CoreInitDelegate.MAX_RECOMMENDED_PRIORITY + 300;
|
||
public blocking = true;
|
||
|
||
protected VERSION_APPLIED = 'version_applied';
|
||
protected logger;
|
||
|
||
constructor(logger: CoreLoggerProvider, private configProvider: CoreConfigProvider, private sitesProvider: CoreSitesProvider,
|
||
private filepoolProvider: CoreFilepoolProvider, private notifProvider: CoreLocalNotificationsProvider) {
|
||
this.logger = logger.getInstance('CoreUpdateManagerProvider');
|
||
}
|
||
|
||
/**
|
||
* Check if the app has been updated and performs the needed processes.
|
||
* This function shouldn't be used outside of core.
|
||
*
|
||
* @return {Promise<any>} Promise resolved when the update process finishes.
|
||
*/
|
||
load() : Promise<any> {
|
||
let promises = [],
|
||
versionCode = CoreConfigConstants.versioncode;
|
||
|
||
return this.configProvider.get(this.VERSION_APPLIED, 0).then((versionApplied: number) => {
|
||
// @todo: Migrate all data from ydn-db to SQLite if there is no versionApplied.
|
||
|
||
if (versionCode >= 2013 && versionApplied < 2013) {
|
||
promises.push(this.migrateFileExtensions());
|
||
}
|
||
|
||
if (versionCode >= 2017 && versionApplied < 2017) {
|
||
promises.push(this.setCalendarDefaultNotifTime());
|
||
promises.push(this.setSitesConfig());
|
||
}
|
||
|
||
if (versionCode >= 2018 && versionApplied < 2018) {
|
||
promises.push(this.adaptForumOfflineStores());
|
||
}
|
||
|
||
return Promise.all(promises).then(() => {
|
||
return this.configProvider.set(this.VERSION_APPLIED, versionCode);
|
||
}).catch((error) => {
|
||
this.logger.error(`Error applying update from ${versionApplied} to ${versionCode}`, error);
|
||
});
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Migrates files filling extensions.
|
||
*
|
||
* @return {Promise<any>} Promise resolved when the site migration is finished.
|
||
*/
|
||
protected migrateFileExtensions() : Promise<any> {
|
||
return this.sitesProvider.getSitesIds().then((sites) => {
|
||
let promises = [];
|
||
sites.forEach((siteId) => {
|
||
promises.push(this.filepoolProvider.fillMissingExtensionInFiles(siteId));
|
||
});
|
||
promises.push(this.filepoolProvider.treatExtensionInQueue());
|
||
return Promise.all(promises);
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Calendar default notification time is configurable from version 3.2.1, and a new option "Default" is added.
|
||
* All events that were configured to use the fixed default time should now be configured to use "Default" option.
|
||
*
|
||
* @return {Promise<any>} Promise resolved when the events are configured.
|
||
*/
|
||
protected setCalendarDefaultNotifTime() : Promise<any> {
|
||
if (!this.notifProvider.isAvailable()) {
|
||
// Local notifications not available, nothing to do.
|
||
return Promise.resolve();
|
||
}
|
||
|
||
// @todo: Implement it once Calendar addon is implemented.
|
||
return Promise.resolve();
|
||
}
|
||
|
||
/**
|
||
* In version 3.2.1 we want the site config to be stored in each site if available.
|
||
* Since it can be slow, we'll only block retrieving the config of current site, the rest will be in background.
|
||
*
|
||
* @return {Promise<any>} Promise resolved when the config is loaded for the current site (if any).
|
||
*/
|
||
protected setSitesConfig() : Promise<any> {
|
||
return this.sitesProvider.getSitesIds().then((siteIds) => {
|
||
|
||
return this.sitesProvider.getStoredCurrentSiteId().catch(() => {
|
||
// Error getting current site.
|
||
}).then((currentSiteId) => {
|
||
let promise;
|
||
|
||
// Load the config of current site first.
|
||
if (currentSiteId) {
|
||
promise = this.setSiteConfig(currentSiteId);
|
||
} else {
|
||
promise = Promise.resolve();
|
||
}
|
||
|
||
// Load the config of rest of sites in background.
|
||
siteIds.forEach((siteId) => {
|
||
if (siteId != currentSiteId) {
|
||
this.setSiteConfig(siteId);
|
||
}
|
||
});
|
||
|
||
return promise;
|
||
});
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Store the config of a site.
|
||
*
|
||
* @param {String} siteId Site ID.
|
||
* @return {Promise<any>} Promise resolved when the config is loaded for the site.
|
||
*/
|
||
protected setSiteConfig(siteId: string) : Promise<any> {
|
||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||
if (site.getStoredConfig() || !site.wsAvailable('tool_mobile_get_config')) {
|
||
// Site already has the config or it cannot be retrieved. Stop.
|
||
return;
|
||
}
|
||
|
||
// Get the site config.
|
||
return site.getConfig().then((config) => {
|
||
return this.sitesProvider.addSite(
|
||
site.getId(), site.getURL(), site.getToken(), site.getInfo(), site.getPrivateToken(), config);
|
||
}).catch(() => {
|
||
// Ignore errors.
|
||
});
|
||
});
|
||
}
|
||
|
||
/**
|
||
* The data stored for offline discussions and posts changed its format. Adapt the entries already stored.
|
||
* Since it can be slow, we'll only block migrating the db of current site, the rest will be in background.
|
||
*
|
||
* @return {Promise<any>} Promise resolved when the db is migrated.
|
||
*/
|
||
protected adaptForumOfflineStores() : Promise<any> {
|
||
// @todo: Implement it once Forum addon is implemented.
|
||
return Promise.resolve();
|
||
}
|
||
}
|