forked from EVOgeek/Vmeda.Online
		
	MOBILE-3565 core: Fix some ESLint of CoreWSProvider
This commit is contained in:
		
							parent
							
								
									5cb0c6fe0c
								
							
						
					
					
						commit
						e7de01acf6
					
				| @ -13,7 +13,7 @@ | |||||||
| // limitations under the License.
 | // limitations under the License.
 | ||||||
| 
 | 
 | ||||||
| import { Injectable } from '@angular/core'; | import { Injectable } from '@angular/core'; | ||||||
| import { HttpResponse } from '@angular/common/http'; | import { HttpResponse, HttpParams } from '@angular/common/http'; | ||||||
| 
 | 
 | ||||||
| import { FileUploadOptions } from '@ionic-native/file-transfer/ngx'; | import { FileUploadOptions } from '@ionic-native/file-transfer/ngx'; | ||||||
| import { Md5 } from 'ts-md5/dist/md5'; | import { Md5 } from 'ts-md5/dist/md5'; | ||||||
| @ -25,20 +25,28 @@ import { CoreApp } from '@services/app'; | |||||||
| import { CoreFile, CoreFileProvider } from '@services/file'; | import { CoreFile, CoreFileProvider } from '@services/file'; | ||||||
| import { CoreMimetypeUtils } from '@services/utils/mimetype'; | import { CoreMimetypeUtils } from '@services/utils/mimetype'; | ||||||
| import { CoreTextUtils } from '@services/utils/text'; | import { CoreTextUtils } from '@services/utils/text'; | ||||||
|  | import { CoreUtils, PromiseDefer } from '@services/utils/utils'; | ||||||
| import { CoreConstants } from '@core/constants'; | import { CoreConstants } from '@core/constants'; | ||||||
|  | import { CoreError } from '@classes/errors/error'; | ||||||
| import { CoreInterceptor } from '@classes/interceptor'; | import { CoreInterceptor } from '@classes/interceptor'; | ||||||
| import { makeSingleton, Translate, FileTransfer, Http, Platform } from '@singletons/core.singletons'; | import { makeSingleton, Translate, FileTransfer, Http, Platform, NativeHttp } from '@singletons/core.singletons'; | ||||||
|  | import { CoreArray } from '@singletons/array'; | ||||||
| import { CoreLogger } from '@singletons/logger'; | import { CoreLogger } from '@singletons/logger'; | ||||||
|  | import { CoreWSError } from '@classes/errors/wserror'; | ||||||
|  | import { CoreAjaxError } from '@classes/errors/ajaxerror'; | ||||||
|  | import { CoreAjaxWSError } from '@classes/errors/ajaxwserror'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * This service allows performing WS calls and download/upload files. |  * This service allows performing WS calls and download/upload files. | ||||||
|  */ |  */ | ||||||
| @Injectable() | @Injectable() | ||||||
| export class CoreWSProvider { | export class CoreWSProvider { | ||||||
|  | 
 | ||||||
|     protected logger: CoreLogger; |     protected logger: CoreLogger; | ||||||
|     protected mimeTypeCache = {}; // A "cache" to store file mimetypes to prevent performing too many HEAD requests.
 |     protected mimeTypeCache: {[url: string]: string} = {}; // A "cache" to store file mimetypes to decrease HEAD requests.
 | ||||||
|     protected ongoingCalls = {}; |     // eslint-disable-next-line @typescript-eslint/no-explicit-any
 | ||||||
|     protected retryCalls = []; |     protected ongoingCalls: {[queueItemId: string]: Promise<any>} = {}; | ||||||
|  |     protected retryCalls: RetryCall[] = []; | ||||||
|     protected retryTimeout = 0; |     protected retryTimeout = 0; | ||||||
| 
 | 
 | ||||||
|     constructor() { |     constructor() { | ||||||
| @ -46,7 +54,7 @@ export class CoreWSProvider { | |||||||
| 
 | 
 | ||||||
|         Platform.instance.ready().then(() => { |         Platform.instance.ready().then(() => { | ||||||
|             if (CoreApp.instance.isIOS()) { |             if (CoreApp.instance.isIOS()) { | ||||||
|                 (<any> cordova).plugin.http.setHeader('User-Agent', navigator.userAgent); |                 NativeHttp.instance.setHeader('*', 'User-Agent', navigator.userAgent); | ||||||
|             } |             } | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| @ -61,20 +69,15 @@ export class CoreWSProvider { | |||||||
|      * @return Deferred promise resolved with the response data in success and rejected with the error message |      * @return Deferred promise resolved with the response data in success and rejected with the error message | ||||||
|      *         if it fails. |      *         if it fails. | ||||||
|      */ |      */ | ||||||
|     protected addToRetryQueue(method: string, siteUrl: string, ajaxData: any, preSets: CoreWSPreSets): Promise<any> { |     protected addToRetryQueue<T = unknown>(method: string, siteUrl: string, data: unknown, preSets: CoreWSPreSets): Promise<T> { | ||||||
|         const call: any = { |         const call = { | ||||||
|             method, |             method, | ||||||
|             siteUrl, |             siteUrl, | ||||||
|             ajaxData, |             data, | ||||||
|             preSets, |             preSets, | ||||||
|             deferred: {} |             deferred: CoreUtils.instance.promiseDefer<T>(), | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         call.deferred.promise = new Promise((resolve, reject): void => { |  | ||||||
|             call.deferred.resolve = resolve; |  | ||||||
|             call.deferred.reject = reject; |  | ||||||
|         }); |  | ||||||
| 
 |  | ||||||
|         this.retryCalls.push(call); |         this.retryCalls.push(call); | ||||||
| 
 | 
 | ||||||
|         return call.deferred.promise; |         return call.deferred.promise; | ||||||
| @ -88,14 +91,11 @@ export class CoreWSProvider { | |||||||
|      * @param preSets Extra settings and information. |      * @param preSets Extra settings and information. | ||||||
|      * @return Promise resolved with the response data in success and rejected if it fails. |      * @return Promise resolved with the response data in success and rejected if it fails. | ||||||
|      */ |      */ | ||||||
|     call(method: string, data: any, preSets: CoreWSPreSets): Promise<any> { |     call<T = unknown>(method: string, data: unknown, preSets: CoreWSPreSets): Promise<T> { | ||||||
| 
 |  | ||||||
|         let siteUrl; |  | ||||||
| 
 |  | ||||||
|         if (!preSets) { |         if (!preSets) { | ||||||
|             return Promise.reject(this.createFakeWSError('core.unexpectederror', true)); |             return Promise.reject(new CoreError(Translate.instance.instant('core.unexpectederror'))); | ||||||
|         } else if (!CoreApp.instance.isOnline()) { |         } else if (!CoreApp.instance.isOnline()) { | ||||||
|             return Promise.reject(this.createFakeWSError('core.networkerrormsg', true)); |             return Promise.reject(new CoreError(Translate.instance.instant('core.networkerrormsg'))); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         preSets.typeExpected = preSets.typeExpected || 'object'; |         preSets.typeExpected = preSets.typeExpected || 'object'; | ||||||
| @ -103,18 +103,18 @@ export class CoreWSProvider { | |||||||
|             preSets.responseExpected = true; |             preSets.responseExpected = true; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         data = Object.assign({}, data); // Create a new object so the changes don't affect the original data.
 |         const dataToSend = Object.assign({}, data); // Create a new object so the changes don't affect the original data.
 | ||||||
|         data.wsfunction = method; |         dataToSend['wsfunction'] = method; | ||||||
|         data.wstoken = preSets.wsToken; |         dataToSend['wstoken'] = preSets.wsToken; | ||||||
|         siteUrl = preSets.siteUrl + '/webservice/rest/server.php?moodlewsrestformat=json'; |         const siteUrl = preSets.siteUrl + '/webservice/rest/server.php?moodlewsrestformat=json'; | ||||||
| 
 | 
 | ||||||
|         // There are some ongoing retry calls, wait for timeout.
 |         // There are some ongoing retry calls, wait for timeout.
 | ||||||
|         if (this.retryCalls.length > 0) { |         if (this.retryCalls.length > 0) { | ||||||
|             this.logger.warn('Calls locked, trying later...'); |             this.logger.warn('Calls locked, trying later...'); | ||||||
| 
 | 
 | ||||||
|             return this.addToRetryQueue(method, siteUrl, data, preSets); |             return this.addToRetryQueue<T>(method, siteUrl, data, preSets); | ||||||
|         } else { |         } else { | ||||||
|             return this.performPost(method, siteUrl, data, preSets); |             return this.performPost<T>(method, siteUrl, data, preSets); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -130,17 +130,17 @@ export class CoreWSProvider { | |||||||
|      *         - errorcode: Error code returned by the site (if any). |      *         - errorcode: Error code returned by the site (if any). | ||||||
|      *         - available: 0 if unknown, 1 if available, -1 if not available. |      *         - available: 0 if unknown, 1 if available, -1 if not available. | ||||||
|      */ |      */ | ||||||
|     callAjax(method: string, data: any, preSets: CoreWSAjaxPreSets): Promise<any> { |     callAjax<T = unknown>(method: string, data: Record<string, unknown>, preSets: CoreWSAjaxPreSets): Promise<T> { | ||||||
|         const cacheParams = { |         const cacheParams = { | ||||||
|             methodname: method, |             methodname: method, | ||||||
|             args: data, |             args: data, | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         let promise = this.getPromiseHttp('ajax', preSets.siteUrl, cacheParams); |         let promise = this.getPromiseHttp<T>('ajax', preSets.siteUrl, cacheParams); | ||||||
| 
 | 
 | ||||||
|         if (!promise) { |         if (!promise) { | ||||||
|             promise = this.performAjax(method, data, preSets); |             promise = this.performAjax<T>(method, data, preSets); | ||||||
|             promise = this.setPromiseHttp(promise, 'ajax', preSets.siteUrl, cacheParams); |             promise = this.setPromiseHttp<T>(promise, 'ajax', preSets.siteUrl, cacheParams); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return promise; |         return promise; | ||||||
| @ -154,7 +154,9 @@ export class CoreWSProvider { | |||||||
|      * @param stripUnicode If Unicode long chars need to be stripped. |      * @param stripUnicode If Unicode long chars need to be stripped. | ||||||
|      * @return The cleaned object or null if some strings becomes empty after stripping Unicode. |      * @return The cleaned object or null if some strings becomes empty after stripping Unicode. | ||||||
|      */ |      */ | ||||||
|  |     // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
 | ||||||
|     convertValuesToString(data: any, stripUnicode?: boolean): any { |     convertValuesToString(data: any, stripUnicode?: boolean): any { | ||||||
|  |         // eslint-disable-next-line @typescript-eslint/no-explicit-any
 | ||||||
|         const result: any = Array.isArray(data) ? [] : {}; |         const result: any = Array.isArray(data) ? [] : {}; | ||||||
| 
 | 
 | ||||||
|         for (const key in data) { |         for (const key in data) { | ||||||
| @ -210,15 +212,14 @@ export class CoreWSProvider { | |||||||
|      * @param needsTranslate If the message needs to be translated. |      * @param needsTranslate If the message needs to be translated. | ||||||
|      * @param translateParams Translation params, if needed. |      * @param translateParams Translation params, if needed. | ||||||
|      * @return Fake WS error. |      * @return Fake WS error. | ||||||
|  |      * @deprecated since 3.9.5. Just create the error directly. | ||||||
|      */ |      */ | ||||||
|     createFakeWSError(message: string, needsTranslate?: boolean, translateParams?: {}): CoreWSError { |     createFakeWSError(message: string, needsTranslate?: boolean, translateParams?: {[name: string]: string}): CoreError { | ||||||
|         if (needsTranslate) { |         if (needsTranslate) { | ||||||
|             message = Translate.instance.instant(message, translateParams); |             message = Translate.instance.instant(message, translateParams); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return { |         return new CoreError(message); | ||||||
|             message, |  | ||||||
|         }; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
| @ -230,71 +231,68 @@ export class CoreWSProvider { | |||||||
|      * @param onProgress Function to call on progress. |      * @param onProgress Function to call on progress. | ||||||
|      * @return Promise resolved with the downloaded file. |      * @return Promise resolved with the downloaded file. | ||||||
|      */ |      */ | ||||||
|     downloadFile(url: string, path: string, addExtension?: boolean, onProgress?: (event: ProgressEvent) => any): Promise<any> { |     async downloadFile(url: string, path: string, addExtension?: boolean, onProgress?: (event: ProgressEvent) => void): | ||||||
|  |             Promise<CoreWSDownloadedFileEntry> { | ||||||
|         this.logger.debug('Downloading file', url, path, addExtension); |         this.logger.debug('Downloading file', url, path, addExtension); | ||||||
| 
 | 
 | ||||||
|         if (!CoreApp.instance.isOnline()) { |         if (!CoreApp.instance.isOnline()) { | ||||||
|             return Promise.reject(Translate.instance.instant('core.networkerrormsg')); |             throw new CoreError(Translate.instance.instant('core.networkerrormsg')); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // Use a tmp path to download the file and then move it to final location.
 |         // Use a tmp path to download the file and then move it to final location.
 | ||||||
|         // This is because if the download fails, the local file is deleted.
 |         // This is because if the download fails, the local file is deleted.
 | ||||||
|         const tmpPath = path + '.tmp'; |         const tmpPath = path + '.tmp'; | ||||||
| 
 | 
 | ||||||
|         // Create the tmp file as an empty file.
 |         try { | ||||||
|         return CoreFile.instance.createFile(tmpPath).then((fileEntry) => { |             // Create the tmp file as an empty file.
 | ||||||
|  |             const fileEntry = await CoreFile.instance.createFile(tmpPath); | ||||||
|  | 
 | ||||||
|             const transfer = FileTransfer.instance.create(); |             const transfer = FileTransfer.instance.create(); | ||||||
|             transfer.onProgress(onProgress); |             transfer.onProgress(onProgress); | ||||||
| 
 | 
 | ||||||
|             return transfer.download(url, fileEntry.toURL(), true).then(() => { |             // Download the file in the tmp file.
 | ||||||
|                 let promise; |             await transfer.download(url, fileEntry.toURL(), true); | ||||||
| 
 | 
 | ||||||
|                 if (addExtension) { |             let extension = ''; | ||||||
|                     const ext = CoreMimetypeUtils.instance.getFileExtension(path); |  | ||||||
| 
 | 
 | ||||||
|                     // Google Drive extensions will be considered invalid since Moodle usually converts them.
 |             if (addExtension) { | ||||||
|                     if (!ext || ext == 'gdoc' || ext == 'gsheet' || ext == 'gslides' || ext == 'gdraw' || ext == 'php') { |                 extension = CoreMimetypeUtils.instance.getFileExtension(path); | ||||||
|                         // Not valid, get the file's mimetype.
 |  | ||||||
|                         promise = this.getRemoteFileMimeType(url).then((mime) => { |  | ||||||
|                             if (mime) { |  | ||||||
|                                 const remoteExt = CoreMimetypeUtils.instance.getExtension(mime, url); |  | ||||||
|                                 // If the file is from Google Drive, ignore mimetype application/json.
 |  | ||||||
|                                 if (remoteExt && (!ext || mime != 'application/json')) { |  | ||||||
|                                     if (ext) { |  | ||||||
|                                         // Remove existing extension since we will use another one.
 |  | ||||||
|                                         path = CoreMimetypeUtils.instance.removeExtension(path); |  | ||||||
|                                     } |  | ||||||
|                                     path += '.' + remoteExt; |  | ||||||
| 
 | 
 | ||||||
|                                     return remoteExt; |                 // Google Drive extensions will be considered invalid since Moodle usually converts them.
 | ||||||
|                                 } |                 if (!extension || CoreArray.contains(['gdoc', 'gsheet', 'gslides', 'gdraw', 'php'], extension)) { | ||||||
|  |                     // Not valid, get the file's mimetype.
 | ||||||
|  |                     const mimetype = await this.getRemoteFileMimeType(url); | ||||||
|  | 
 | ||||||
|  |                     if (mimetype) { | ||||||
|  |                         const remoteExtension = CoreMimetypeUtils.instance.getExtension(mimetype, url); | ||||||
|  |                         // If the file is from Google Drive, ignore mimetype application/json.
 | ||||||
|  |                         if (remoteExtension && (!extension || mimetype != 'application/json')) { | ||||||
|  |                             if (extension) { | ||||||
|  |                                 // Remove existing extension since we will use another one.
 | ||||||
|  |                                 path = CoreMimetypeUtils.instance.removeExtension(path); | ||||||
|                             } |                             } | ||||||
|  |                             path += '.' + remoteExtension; | ||||||
| 
 | 
 | ||||||
|                             return ext; |                             extension = remoteExtension; | ||||||
|                         }); |                         } | ||||||
|                     } else { |  | ||||||
|                         promise = Promise.resolve(ext); |  | ||||||
|                     } |                     } | ||||||
|                 } else { |  | ||||||
|                     promise = Promise.resolve(''); |  | ||||||
|                 } |                 } | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|                 return promise.then((extension) => { |             // Move the file to the final location.
 | ||||||
|                     return CoreFile.instance.moveFile(tmpPath, path).then((movedEntry) => { |             const movedEntry: CoreWSDownloadedFileEntry = await CoreFile.instance.moveFile(tmpPath, path); | ||||||
|                         // Save the extension.
 |  | ||||||
|                         movedEntry.extension = extension; |  | ||||||
|                         movedEntry.path = path; |  | ||||||
|                         this.logger.debug(`Success downloading file ${url} to ${path} with extension ${extension}`); |  | ||||||
| 
 | 
 | ||||||
|                         return movedEntry; |             // Save the extension.
 | ||||||
|                     }); |             movedEntry.extension = extension; | ||||||
|                 }); |             movedEntry.path = path; | ||||||
|             }); |             this.logger.debug(`Success downloading file ${url} to ${path} with extension ${extension}`); | ||||||
|         }).catch((err) => { |  | ||||||
|             this.logger.error(`Error downloading ${url} to ${path}`, err); |  | ||||||
| 
 | 
 | ||||||
|             return Promise.reject(err); |             return movedEntry; | ||||||
|         }); |         } catch (error) { | ||||||
|  |             this.logger.error(`Error downloading ${url} to ${path}`, error); | ||||||
|  | 
 | ||||||
|  |             throw error; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
| @ -304,13 +302,11 @@ export class CoreWSProvider { | |||||||
|      * @param url Base URL of the HTTP request. |      * @param url Base URL of the HTTP request. | ||||||
|      * @param params Params of the HTTP request. |      * @param params Params of the HTTP request. | ||||||
|      */ |      */ | ||||||
|     protected getPromiseHttp(method: string, url: string, params?: any): any { |     protected getPromiseHttp<T = unknown>(method: string, url: string, params?: Record<string, unknown>): Promise<T> { | ||||||
|         const queueItemId = this.getQueueItemId(method, url, params); |         const queueItemId = this.getQueueItemId(method, url, params); | ||||||
|         if (typeof this.ongoingCalls[queueItemId] != 'undefined') { |         if (typeof this.ongoingCalls[queueItemId] != 'undefined') { | ||||||
|             return this.ongoingCalls[queueItemId]; |             return this.ongoingCalls[queueItemId]; | ||||||
|         } |         } | ||||||
| 
 |  | ||||||
|         return false; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
| @ -334,10 +330,10 @@ export class CoreWSProvider { | |||||||
|             this.mimeTypeCache[url] = mimeType; |             this.mimeTypeCache[url] = mimeType; | ||||||
| 
 | 
 | ||||||
|             return mimeType || ''; |             return mimeType || ''; | ||||||
|         }).catch(() => { |         }).catch(() => | ||||||
|             // Error, resolve with empty mimetype.
 |             // Error, resolve with empty mimetype.
 | ||||||
|             return ''; |             '', | ||||||
|         }); |         ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
| @ -355,10 +351,10 @@ export class CoreWSProvider { | |||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             return -1; |             return -1; | ||||||
|         }).catch(() => { |         }).catch(() => | ||||||
|             // Error, return -1.
 |             // Error, return -1.
 | ||||||
|             return -1; |             -1, | ||||||
|         }); |         ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
| @ -378,7 +374,7 @@ export class CoreWSProvider { | |||||||
|      * @param params Params of the HTTP request. |      * @param params Params of the HTTP request. | ||||||
|      * @return Queue item ID. |      * @return Queue item ID. | ||||||
|      */ |      */ | ||||||
|     protected getQueueItemId(method: string, url: string, params?: any): string { |     protected getQueueItemId(method: string, url: string, params?: Record<string, unknown>): string { | ||||||
|         if (params) { |         if (params) { | ||||||
|             url += '###' + CoreInterceptor.serialize(params); |             url += '###' + CoreInterceptor.serialize(params); | ||||||
|         } |         } | ||||||
| @ -397,14 +393,14 @@ export class CoreWSProvider { | |||||||
|      *         - errorcode: Error code returned by the site (if any). |      *         - errorcode: Error code returned by the site (if any). | ||||||
|      *         - available: 0 if unknown, 1 if available, -1 if not available. |      *         - available: 0 if unknown, 1 if available, -1 if not available. | ||||||
|      */ |      */ | ||||||
|     protected performAjax(method: string, data: any, preSets: CoreWSAjaxPreSets): Promise<any> { |     protected performAjax<T = unknown>(method: string, data: Record<string, unknown>, preSets: CoreWSAjaxPreSets): Promise<T> { | ||||||
| 
 |         // eslint-disable-next-line @typescript-eslint/no-explicit-any
 | ||||||
|         let promise; |         let promise: Promise<HttpResponse<any>>; | ||||||
| 
 | 
 | ||||||
|         if (typeof preSets.siteUrl == 'undefined') { |         if (typeof preSets.siteUrl == 'undefined') { | ||||||
|             return rejectWithError(this.createFakeWSError('core.unexpectederror', true)); |             return Promise.reject(new CoreAjaxError(Translate.instance.instant('core.unexpectederror'))); | ||||||
|         } else if (!CoreApp.instance.isOnline()) { |         } else if (!CoreApp.instance.isOnline()) { | ||||||
|             return rejectWithError(this.createFakeWSError('core.networkerrormsg', true)); |             return Promise.reject(new CoreAjaxError(Translate.instance.instant('core.networkerrormsg'))); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (typeof preSets.responseExpected == 'undefined') { |         if (typeof preSets.responseExpected == 'undefined') { | ||||||
| @ -415,7 +411,7 @@ export class CoreWSProvider { | |||||||
|         const ajaxData = [{ |         const ajaxData = [{ | ||||||
|             index: 0, |             index: 0, | ||||||
|             methodname: method, |             methodname: method, | ||||||
|             args: this.convertValuesToString(data) |             args: this.convertValuesToString(data), | ||||||
|         }]; |         }]; | ||||||
| 
 | 
 | ||||||
|         // The info= parameter has no function. It is just to help with debugging.
 |         // The info= parameter has no function. It is just to help with debugging.
 | ||||||
| @ -426,18 +422,19 @@ export class CoreWSProvider { | |||||||
|             // Send params using GET.
 |             // Send params using GET.
 | ||||||
|             siteUrl += '&args=' + encodeURIComponent(JSON.stringify(ajaxData)); |             siteUrl += '&args=' + encodeURIComponent(JSON.stringify(ajaxData)); | ||||||
| 
 | 
 | ||||||
|             promise = this.sendHTTPRequest(siteUrl, { |             promise = this.sendHTTPRequest<T>(siteUrl, { | ||||||
|                 method: 'get', |                 method: 'get', | ||||||
|             }); |             }); | ||||||
|         } else { |         } else { | ||||||
|             promise = this.sendHTTPRequest(siteUrl, { |             promise = this.sendHTTPRequest<T>(siteUrl, { | ||||||
|                 method: 'post', |                 method: 'post', | ||||||
|                 data: ajaxData, |                 // eslint-disable-next-line @typescript-eslint/no-explicit-any
 | ||||||
|  |                 data: <any> ajaxData, | ||||||
|                 serializer: 'json', |                 serializer: 'json', | ||||||
|             }); |             }); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return promise.then((response: HttpResponse<any>) => { |         return promise.then((response) => { | ||||||
|             let data = response.body; |             let data = response.body; | ||||||
| 
 | 
 | ||||||
|             // Some moodle web services return null.
 |             // Some moodle web services return null.
 | ||||||
| @ -448,39 +445,24 @@ export class CoreWSProvider { | |||||||
| 
 | 
 | ||||||
|             // Check if error. Ajax layer should always return an object (if error) or an array (if success).
 |             // Check if error. Ajax layer should always return an object (if error) or an array (if success).
 | ||||||
|             if (!data || typeof data != 'object') { |             if (!data || typeof data != 'object') { | ||||||
|                 return rejectWithError(this.createFakeWSError('core.serverconnection', true)); |                 return Promise.reject(new CoreAjaxError(Translate.instance.instant('core.serverconnection'))); | ||||||
|             } else if (data.error) { |             } else if (data.error) { | ||||||
|                 return rejectWithError(data); |                 return Promise.reject(new CoreAjaxWSError(data)); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             // Get the first response since only one request was done.
 |             // Get the first response since only one request was done.
 | ||||||
|             data = data[0]; |             data = data[0]; | ||||||
| 
 | 
 | ||||||
|             if (data.error) { |             if (data.error) { | ||||||
|                 return rejectWithError(data.exception); |                 return Promise.reject(new CoreAjaxWSError(data.exception)); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             return data.data; |             return data.data; | ||||||
|         }, (data) => { |         }, (data) => { | ||||||
|             const available = data.status == 404 ? -1 : 0; |             const available = data.status == 404 ? -1 : 0; | ||||||
| 
 | 
 | ||||||
|             return rejectWithError(this.createFakeWSError('core.serverconnection', true), available); |             return Promise.reject(new CoreAjaxError(Translate.instance.instant('core.serverconnection'), available)); | ||||||
|         }); |         }); | ||||||
| 
 |  | ||||||
|         // Convenience function to return an error.
 |  | ||||||
|         function rejectWithError(exception: any, available?: number): Promise<never> { |  | ||||||
|             if (typeof available == 'undefined') { |  | ||||||
|                 if (exception.errorcode) { |  | ||||||
|                     available = exception.errorcode == 'invalidrecord' ? -1 : 1; |  | ||||||
|                 } else { |  | ||||||
|                     available = 0; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             exception.available = available; |  | ||||||
| 
 |  | ||||||
|             return Promise.reject(exception); |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
| @ -489,16 +471,16 @@ export class CoreWSProvider { | |||||||
|      * @param url URL to perform the request. |      * @param url URL to perform the request. | ||||||
|      * @return Promise resolved with the response. |      * @return Promise resolved with the response. | ||||||
|      */ |      */ | ||||||
|     performHead(url: string): Promise<HttpResponse<any>> { |     performHead<T = unknown>(url: string): Promise<HttpResponse<T>> { | ||||||
|         let promise = this.getPromiseHttp('head', url); |         let promise = this.getPromiseHttp<HttpResponse<T>>('head', url); | ||||||
| 
 | 
 | ||||||
|         if (!promise) { |         if (!promise) { | ||||||
|             promise = this.sendHTTPRequest(url, { |             promise = this.sendHTTPRequest<T>(url, { | ||||||
|                 method: 'head', |                 method: 'head', | ||||||
|                 responseType: 'text', |                 responseType: 'text', | ||||||
|             }); |             }); | ||||||
| 
 | 
 | ||||||
|             promise = this.setPromiseHttp(promise, 'head', url); |             promise = this.setPromiseHttp<HttpResponse<T>>(promise, 'head', url); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return promise; |         return promise; | ||||||
| @ -513,12 +495,12 @@ export class CoreWSProvider { | |||||||
|      * @param preSets Extra settings and information. |      * @param preSets Extra settings and information. | ||||||
|      * @return Promise resolved with the response data in success and rejected with CoreWSError if it fails. |      * @return Promise resolved with the response data in success and rejected with CoreWSError if it fails. | ||||||
|      */ |      */ | ||||||
|     performPost(method: string, siteUrl: string, ajaxData: any, preSets: CoreWSPreSets): Promise<any> { |     performPost<T = unknown>(method: string, siteUrl: string, ajaxData: unknown, preSets: CoreWSPreSets): Promise<T> { | ||||||
|  |         // eslint-disable-next-line @typescript-eslint/no-explicit-any
 | ||||||
|         const options: any = {}; |         const options: any = {}; | ||||||
| 
 | 
 | ||||||
|         // This is done because some returned values like 0 are treated as null if responseType is json.
 |         // This is done because some returned values like 0 are treated as null if responseType is json.
 | ||||||
|         if (preSets.typeExpected == 'number' || preSets.typeExpected == 'boolean' || preSets.typeExpected == 'string') { |         if (preSets.typeExpected == 'number' || preSets.typeExpected == 'boolean' || preSets.typeExpected == 'string') { | ||||||
|             // Avalaible values are: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType
 |  | ||||||
|             options.responseType = 'text'; |             options.responseType = 'text'; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -530,8 +512,8 @@ export class CoreWSProvider { | |||||||
|         // Perform the post request.
 |         // Perform the post request.
 | ||||||
|         const promise = Http.instance.post(requestUrl, ajaxData, options).pipe(timeout(this.getRequestTimeout())).toPromise(); |         const promise = Http.instance.post(requestUrl, ajaxData, options).pipe(timeout(this.getRequestTimeout())).toPromise(); | ||||||
| 
 | 
 | ||||||
|  |         // eslint-disable-next-line @typescript-eslint/no-explicit-any
 | ||||||
|         return promise.then((data: any) => { |         return promise.then((data: any) => { | ||||||
| 
 |  | ||||||
|             // Some moodle web services return null.
 |             // Some moodle web services return null.
 | ||||||
|             // If the responseExpected value is set to false, we create a blank object if the response is null.
 |             // If the responseExpected value is set to false, we create a blank object if the response is null.
 | ||||||
|             if (!data && !preSets.responseExpected) { |             if (!data && !preSets.responseExpected) { | ||||||
| @ -539,7 +521,7 @@ export class CoreWSProvider { | |||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (!data) { |             if (!data) { | ||||||
|                 return Promise.reject(this.createFakeWSError('core.serverconnection', true)); |                 return Promise.reject(new CoreError(Translate.instance.instant('core.serverconnection'))); | ||||||
|             } else if (typeof data != preSets.typeExpected) { |             } else if (typeof data != preSets.typeExpected) { | ||||||
|                 // If responseType is text an string will be returned, parse before returning.
 |                 // If responseType is text an string will be returned, parse before returning.
 | ||||||
|                 if (typeof data == 'string') { |                 if (typeof data == 'string') { | ||||||
| @ -548,7 +530,7 @@ export class CoreWSProvider { | |||||||
|                         if (isNaN(data)) { |                         if (isNaN(data)) { | ||||||
|                             this.logger.warn(`Response expected type "${preSets.typeExpected}" cannot be parsed to number`); |                             this.logger.warn(`Response expected type "${preSets.typeExpected}" cannot be parsed to number`); | ||||||
| 
 | 
 | ||||||
|                             return Promise.reject(this.createFakeWSError('core.errorinvalidresponse', true)); |                             return Promise.reject(new CoreError(Translate.instance.instant('core.errorinvalidresponse'))); | ||||||
|                         } |                         } | ||||||
|                     } else if (preSets.typeExpected == 'boolean') { |                     } else if (preSets.typeExpected == 'boolean') { | ||||||
|                         if (data === 'true') { |                         if (data === 'true') { | ||||||
| @ -558,17 +540,17 @@ export class CoreWSProvider { | |||||||
|                         } else { |                         } else { | ||||||
|                             this.logger.warn(`Response expected type "${preSets.typeExpected}" is not true or false`); |                             this.logger.warn(`Response expected type "${preSets.typeExpected}" is not true or false`); | ||||||
| 
 | 
 | ||||||
|                             return Promise.reject(this.createFakeWSError('core.errorinvalidresponse', true)); |                             return Promise.reject(new CoreError(Translate.instance.instant('core.errorinvalidresponse'))); | ||||||
|                         } |                         } | ||||||
|                     } else { |                     } else { | ||||||
|                         this.logger.warn('Response of type "' + typeof data + `" received, expecting "${preSets.typeExpected}"`); |                         this.logger.warn('Response of type "' + typeof data + `" received, expecting "${preSets.typeExpected}"`); | ||||||
| 
 | 
 | ||||||
|                         return Promise.reject(this.createFakeWSError('core.errorinvalidresponse', true)); |                         return Promise.reject(new CoreError(Translate.instance.instant('core.errorinvalidresponse'))); | ||||||
|                     } |                     } | ||||||
|                 } else { |                 } else { | ||||||
|                     this.logger.warn('Response of type "' + typeof data + `" received, expecting "${preSets.typeExpected}"`); |                     this.logger.warn('Response of type "' + typeof data + `" received, expecting "${preSets.typeExpected}"`); | ||||||
| 
 | 
 | ||||||
|                     return Promise.reject(this.createFakeWSError('core.errorinvalidresponse', true)); |                     return Promise.reject(new CoreError(Translate.instance.instant('core.errorinvalidresponse'))); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
| @ -578,18 +560,18 @@ export class CoreWSProvider { | |||||||
|                     this.logger.error('Error calling WS', method, data); |                     this.logger.error('Error calling WS', method, data); | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 return Promise.reject(data); |                 return Promise.reject(new CoreWSError(data)); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (typeof data.debuginfo != 'undefined') { |             if (typeof data.debuginfo != 'undefined') { | ||||||
|                 return Promise.reject(this.createFakeWSError('Error. ' + data.message)); |                 return Promise.reject(new CoreError('Error. ' + data.message)); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             return data; |             return data; | ||||||
|         }, (error) => { |         }, (error) => { | ||||||
|             // If server has heavy load, retry after some seconds.
 |             // If server has heavy load, retry after some seconds.
 | ||||||
|             if (error.status == 429) { |             if (error.status == 429) { | ||||||
|                 const retryPromise = this.addToRetryQueue(method, siteUrl, ajaxData, preSets); |                 const retryPromise = this.addToRetryQueue<T>(method, siteUrl, ajaxData, preSets); | ||||||
| 
 | 
 | ||||||
|                 // Only process the queue one time.
 |                 // Only process the queue one time.
 | ||||||
|                 if (this.retryTimeout == 0) { |                 if (this.retryTimeout == 0) { | ||||||
| @ -610,7 +592,7 @@ export class CoreWSProvider { | |||||||
|                 return retryPromise; |                 return retryPromise; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             return Promise.reject(this.createFakeWSError('core.serverconnection', true)); |             return Promise.reject(new CoreError(Translate.instance.instant('core.serverconnection'))); | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -623,7 +605,7 @@ export class CoreWSProvider { | |||||||
|             const call = this.retryCalls.shift(); |             const call = this.retryCalls.shift(); | ||||||
|             // Add a delay between calls.
 |             // Add a delay between calls.
 | ||||||
|             setTimeout(() => { |             setTimeout(() => { | ||||||
|                 call.deferred.resolve(this.performPost(call.method, call.siteUrl, call.ajaxData, call.preSets)); |                 call.deferred.resolve(this.performPost(call.method, call.siteUrl, call.data, call.preSets)); | ||||||
|                 this.processRetryQueue(); |                 this.processRetryQueue(); | ||||||
|             }, 200); |             }, 200); | ||||||
|         } else { |         } else { | ||||||
| @ -640,14 +622,14 @@ export class CoreWSProvider { | |||||||
|      * @param params Params of the HTTP request. |      * @param params Params of the HTTP request. | ||||||
|      * @return The promise saved. |      * @return The promise saved. | ||||||
|      */ |      */ | ||||||
|     protected setPromiseHttp(promise: Promise<any>, method: string, url: string, params?: any): Promise<any> { |     protected setPromiseHttp<T = unknown>(promise: Promise<T>, method: string, url: string, params?: Record<string, unknown>): | ||||||
|  |             Promise<T> { | ||||||
|         const queueItemId = this.getQueueItemId(method, url, params); |         const queueItemId = this.getQueueItemId(method, url, params); | ||||||
|         let timeout; |  | ||||||
| 
 | 
 | ||||||
|         this.ongoingCalls[queueItemId] = promise; |         this.ongoingCalls[queueItemId] = promise; | ||||||
| 
 | 
 | ||||||
|         // HTTP not finished, but we should delete the promise after timeout.
 |         // HTTP not finished, but we should delete the promise after timeout.
 | ||||||
|         timeout = setTimeout(() => { |         const timeout = setTimeout(() => { | ||||||
|             delete this.ongoingCalls[queueItemId]; |             delete this.ongoingCalls[queueItemId]; | ||||||
|         }, this.getRequestTimeout()); |         }, this.getRequestTimeout()); | ||||||
| 
 | 
 | ||||||
| @ -667,22 +649,14 @@ export class CoreWSProvider { | |||||||
|      * @param data Arguments to pass to the method. |      * @param data Arguments to pass to the method. | ||||||
|      * @param preSets Extra settings and information. |      * @param preSets Extra settings and information. | ||||||
|      * @return Promise resolved with the response data in success and rejected with the error message if it fails. |      * @return Promise resolved with the response data in success and rejected with the error message if it fails. | ||||||
|      * @return Request response. If the request fails, returns an object with 'error'=true and 'message' properties. |      * @return Request response. | ||||||
|      */ |      */ | ||||||
|     syncCall(method: string, data: any, preSets: CoreWSPreSets): any { |     // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
 | ||||||
|         const errorResponse = { |     syncCall<T = unknown>(method: string, data: any, preSets: CoreWSPreSets): T { | ||||||
|             error: true, |  | ||||||
|             message: '', |  | ||||||
|         }; |  | ||||||
| 
 |  | ||||||
|         if (!preSets) { |         if (!preSets) { | ||||||
|             errorResponse.message = Translate.instance.instant('core.unexpectederror'); |             throw new CoreError(Translate.instance.instant('core.unexpectederror')); | ||||||
| 
 |  | ||||||
|             return errorResponse; |  | ||||||
|         } else if (!CoreApp.instance.isOnline()) { |         } else if (!CoreApp.instance.isOnline()) { | ||||||
|             errorResponse.message = Translate.instance.instant('core.networkerrormsg'); |             throw new CoreError(Translate.instance.instant('core.networkerrormsg')); | ||||||
| 
 |  | ||||||
|             return errorResponse; |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         preSets.typeExpected = preSets.typeExpected || 'object'; |         preSets.typeExpected = preSets.typeExpected || 'object'; | ||||||
| @ -693,9 +667,7 @@ export class CoreWSProvider { | |||||||
|         data = this.convertValuesToString(data || {}, preSets.cleanUnicode); |         data = this.convertValuesToString(data || {}, preSets.cleanUnicode); | ||||||
|         if (data == null) { |         if (data == null) { | ||||||
|             // Empty cleaned text found.
 |             // Empty cleaned text found.
 | ||||||
|             errorResponse.message = Translate.instance.instant('core.unicodenotsupportedcleanerror'); |             throw new CoreError(Translate.instance.instant('core.unicodenotsupportedcleanerror')); | ||||||
| 
 |  | ||||||
|             return errorResponse; |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         data.wsfunction = method; |         data.wsfunction = method; | ||||||
| @ -706,22 +678,21 @@ export class CoreWSProvider { | |||||||
|         data = CoreInterceptor.serialize(data); |         data = CoreInterceptor.serialize(data); | ||||||
| 
 | 
 | ||||||
|         // Perform sync request using XMLHttpRequest.
 |         // Perform sync request using XMLHttpRequest.
 | ||||||
|         const xhr = new (<any> window).XMLHttpRequest(); |         const xhr = new XMLHttpRequest(); | ||||||
|         xhr.open('post', siteUrl, false); |         xhr.open('post', siteUrl, false); | ||||||
|         xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8'); |         xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8'); | ||||||
| 
 | 
 | ||||||
|         xhr.send(data); |         xhr.send(data); | ||||||
| 
 | 
 | ||||||
|         // Get response.
 |         // Get response.
 | ||||||
|         data = ('response' in xhr) ? xhr.response : xhr.responseText; |         // eslint-disable-next-line @typescript-eslint/no-explicit-any
 | ||||||
|  |         data = ('response' in xhr) ? xhr.response : (<any> xhr).responseText; | ||||||
| 
 | 
 | ||||||
|         // Check status.
 |         // Check status.
 | ||||||
|         const status = Math.max(xhr.status === 1223 ? 204 : xhr.status, 0); |         const status = Math.max(xhr.status === 1223 ? 204 : xhr.status, 0); | ||||||
|         if (status < 200 || status >= 300) { |         if (status < 200 || status >= 300) { | ||||||
|             // Request failed.
 |             // Request failed.
 | ||||||
|             errorResponse.message = data; |             throw new CoreError(data); | ||||||
| 
 |  | ||||||
|             return errorResponse; |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // Treat response.
 |         // Treat response.
 | ||||||
| @ -734,18 +705,14 @@ export class CoreWSProvider { | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (!data) { |         if (!data) { | ||||||
|             errorResponse.message = Translate.instance.instant('core.serverconnection'); |             throw new CoreError(Translate.instance.instant('core.serverconnection')); | ||||||
|         } else if (typeof data != preSets.typeExpected) { |         } else if (typeof data != preSets.typeExpected) { | ||||||
|             this.logger.warn('Response of type "' + typeof data + '" received, expecting "' + preSets.typeExpected + '"'); |             this.logger.warn('Response of type "' + typeof data + '" received, expecting "' + preSets.typeExpected + '"'); | ||||||
|             errorResponse.message = Translate.instance.instant('core.errorinvalidresponse'); |             throw new CoreError(Translate.instance.instant('core.errorinvalidresponse')); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (typeof data.exception != 'undefined' || typeof data.debuginfo != 'undefined') { |         if (typeof data.exception != 'undefined' || typeof data.debuginfo != 'undefined') { | ||||||
|             errorResponse.message = data.message; |             throw new CoreWSError(data); | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if (errorResponse.message !== '') { |  | ||||||
|             return errorResponse; |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return data; |         return data; | ||||||
| @ -760,16 +727,16 @@ export class CoreWSProvider { | |||||||
|      * @param onProgress Function to call on progress. |      * @param onProgress Function to call on progress. | ||||||
|      * @return Promise resolved when uploaded. |      * @return Promise resolved when uploaded. | ||||||
|      */ |      */ | ||||||
|     uploadFile(filePath: string, options: CoreWSFileUploadOptions, preSets: CoreWSPreSets, |     uploadFile<T = unknown>(filePath: string, options: CoreWSFileUploadOptions, preSets: CoreWSPreSets, | ||||||
|             onProgress?: (event: ProgressEvent) => any): Promise<any> { |             onProgress?: (event: ProgressEvent) => void): Promise<T> { | ||||||
|         this.logger.debug(`Trying to upload file: ${filePath}`); |         this.logger.debug(`Trying to upload file: ${filePath}`); | ||||||
| 
 | 
 | ||||||
|         if (!filePath || !options || !preSets) { |         if (!filePath || !options || !preSets) { | ||||||
|             return Promise.reject(null); |             return Promise.reject(new CoreError('Invalid options passed to upload file.')); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (!CoreApp.instance.isOnline()) { |         if (!CoreApp.instance.isOnline()) { | ||||||
|             return Promise.reject(Translate.instance.instant('core.networkerrormsg')); |             return Promise.reject(new CoreError(Translate.instance.instant('core.networkerrormsg'))); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         const uploadUrl = preSets.siteUrl + '/webservice/upload.php'; |         const uploadUrl = preSets.siteUrl + '/webservice/upload.php'; | ||||||
| @ -781,34 +748,40 @@ export class CoreWSProvider { | |||||||
|         options.params = { |         options.params = { | ||||||
|             token: preSets.wsToken, |             token: preSets.wsToken, | ||||||
|             filearea: options.fileArea || 'draft', |             filearea: options.fileArea || 'draft', | ||||||
|             itemid: options.itemId || 0 |             itemid: options.itemId || 0, | ||||||
|         }; |         }; | ||||||
|         options.chunkedMode = false; |         options.chunkedMode = false; | ||||||
|         options.headers = { |         options.headers = {}; | ||||||
|             Connection: 'close' |         options['Connection'] = 'close'; | ||||||
|         }; |  | ||||||
| 
 | 
 | ||||||
|         return transfer.upload(filePath, uploadUrl, options, true).then((success) => { |         return transfer.upload(filePath, uploadUrl, options, true).then((success) => { | ||||||
|             const data = CoreTextUtils.instance.parseJSON(success.response, null, |             const data = CoreTextUtils.instance.parseJSON(success.response, null, | ||||||
|                     this.logger.error.bind(this.logger, 'Error parsing response from upload', success.response)); |                 this.logger.error.bind(this.logger, 'Error parsing response from upload', success.response)); | ||||||
|  | 
 | ||||||
|             if (data === null) { |             if (data === null) { | ||||||
|                 return Promise.reject(Translate.instance.instant('core.errorinvalidresponse')); |                 return Promise.reject(new CoreError(Translate.instance.instant('core.errorinvalidresponse'))); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (!data) { |             if (!data) { | ||||||
|                 return Promise.reject(Translate.instance.instant('core.serverconnection')); |                 return Promise.reject(new CoreError(Translate.instance.instant('core.serverconnection'))); | ||||||
|             } else if (typeof data != 'object') { |             } else if (typeof data != 'object') { | ||||||
|                 this.logger.warn('Upload file: Response of type "' + typeof data + '" received, expecting "object"'); |                 this.logger.warn('Upload file: Response of type "' + typeof data + '" received, expecting "object"'); | ||||||
| 
 | 
 | ||||||
|                 return Promise.reject(Translate.instance.instant('core.errorinvalidresponse')); |                 return Promise.reject(new CoreError(Translate.instance.instant('core.errorinvalidresponse'))); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (typeof data.exception !== 'undefined') { |             if (typeof data.exception !== 'undefined') { | ||||||
|                 return Promise.reject(data.message); |                 return Promise.reject(new CoreWSError(data)); | ||||||
|             } else if (data && typeof data.error !== 'undefined') { |             } else if (typeof data.error !== 'undefined') { | ||||||
|                 return Promise.reject(data.error); |                 return Promise.reject(new CoreWSError({ | ||||||
|  |                     errorcode: data.errortype, | ||||||
|  |                     message: data.error, | ||||||
|  |                 })); | ||||||
|             } else if (data[0] && typeof data[0].error !== 'undefined') { |             } else if (data[0] && typeof data[0].error !== 'undefined') { | ||||||
|                 return Promise.reject(data[0].error); |                 return Promise.reject(new CoreWSError({ | ||||||
|  |                     errorcode: data[0].errortype, | ||||||
|  |                     message: data[0].error, | ||||||
|  |                 })); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             // We uploaded only 1 file, so we only return the first file returned.
 |             // We uploaded only 1 file, so we only return the first file returned.
 | ||||||
| @ -818,7 +791,7 @@ export class CoreWSProvider { | |||||||
|         }).catch((error) => { |         }).catch((error) => { | ||||||
|             this.logger.error('Error while uploading file', filePath, error); |             this.logger.error('Error while uploading file', filePath, error); | ||||||
| 
 | 
 | ||||||
|             return Promise.reject(Translate.instance.instant('core.errorinvalidresponse')); |             return Promise.reject(new CoreError(Translate.instance.instant('core.errorinvalidresponse'))); | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -835,7 +808,7 @@ export class CoreWSProvider { | |||||||
|             responseType: 'text', |             responseType: 'text', | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         const response = await this.sendHTTPRequest(url, options); |         const response = await this.sendHTTPRequest<string>(url, options); | ||||||
| 
 | 
 | ||||||
|         const content = response.body; |         const content = response.body; | ||||||
| 
 | 
 | ||||||
| @ -853,8 +826,7 @@ export class CoreWSProvider { | |||||||
|      * @param options Options for the request. |      * @param options Options for the request. | ||||||
|      * @return Promise resolved with the response. |      * @return Promise resolved with the response. | ||||||
|      */ |      */ | ||||||
|     async sendHTTPRequest(url: string, options: HttpRequestOptions): Promise<HttpResponse<any>> { |     async sendHTTPRequest<T = unknown>(url: string, options: HttpRequestOptions): Promise<HttpResponse<T>> { | ||||||
| 
 |  | ||||||
|         // Set default values.
 |         // Set default values.
 | ||||||
|         options.responseType = options.responseType || 'json'; |         options.responseType = options.responseType || 'json'; | ||||||
|         options.timeout = typeof options.timeout == 'undefined' ? this.getRequestTimeout() : options.timeout; |         options.timeout = typeof options.timeout == 'undefined' ? this.getRequestTimeout() : options.timeout; | ||||||
| @ -867,8 +839,8 @@ export class CoreWSProvider { | |||||||
| 
 | 
 | ||||||
|                 const content = await CoreFile.instance.readFile(url, format); |                 const content = await CoreFile.instance.readFile(url, format); | ||||||
| 
 | 
 | ||||||
|                 return new HttpResponse({ |                 return new HttpResponse<T>({ | ||||||
|                     body: content, |                     body: <T> content, | ||||||
|                     headers: null, |                     headers: null, | ||||||
|                     status: 200, |                     status: 200, | ||||||
|                     statusText: 'OK', |                     statusText: 'OK', | ||||||
| @ -876,81 +848,78 @@ export class CoreWSProvider { | |||||||
|                 }); |                 }); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             return new Promise<HttpResponse<any>>((resolve, reject): void => { |             return NativeHttp.instance.sendRequest(url, options).then((response) => new CoreNativeToAngularHttpResponse(response)); | ||||||
|                 // We cannot use Ionic Native plugin because it doesn't have the sendRequest method.
 |  | ||||||
|                 (<any> cordova).plugin.http.sendRequest(url, options, (response) => { |  | ||||||
|                     resolve(new CoreNativeToAngularHttpResponse(response)); |  | ||||||
|                 }, reject); |  | ||||||
|             }); |  | ||||||
|         } else { |         } else { | ||||||
|             let observable: Observable<any>; |             // eslint-disable-next-line @typescript-eslint/no-explicit-any
 | ||||||
|  |             let observable: Observable<HttpResponse<any>>; | ||||||
|  |             const angularOptions = <AngularHttpRequestOptions> options; | ||||||
| 
 | 
 | ||||||
|             // Use Angular's library.
 |             // Use Angular's library.
 | ||||||
|             switch (options.method) { |             switch (angularOptions.method) { | ||||||
|                 case 'get': |                 case 'get': | ||||||
|                     observable = Http.instance.get(url, { |                     observable = Http.instance.get(url, { | ||||||
|                         headers: options.headers, |                         headers: angularOptions.headers, | ||||||
|                         params: options.params, |                         params: angularOptions.params, | ||||||
|                         observe: 'response', |                         observe: 'response', | ||||||
|                         responseType: <any> options.responseType, |                         // eslint-disable-next-line @typescript-eslint/no-explicit-any
 | ||||||
|  |                         responseType: <any> angularOptions.responseType, | ||||||
|                     }); |                     }); | ||||||
|                     break; |                     break; | ||||||
| 
 | 
 | ||||||
|                 case 'post': |                 case 'post': | ||||||
|                     if (options.serializer == 'json') { |                     if (angularOptions.serializer == 'json') { | ||||||
|                         options.data = JSON.stringify(options.data); |                         angularOptions.data = JSON.stringify(angularOptions.data); | ||||||
|                     } |                     } | ||||||
| 
 | 
 | ||||||
|                     observable = Http.instance.post(url, options.data, { |                     observable = Http.instance.post(url, angularOptions.data, { | ||||||
|                         headers: options.headers, |                         headers: angularOptions.headers, | ||||||
|                         observe: 'response', |                         observe: 'response', | ||||||
|                         responseType: <any> options.responseType, |                         // eslint-disable-next-line @typescript-eslint/no-explicit-any
 | ||||||
|  |                         responseType: <any> angularOptions.responseType, | ||||||
|                     }); |                     }); | ||||||
|                     break; |                     break; | ||||||
| 
 | 
 | ||||||
|                 case 'head': |                 case 'head': | ||||||
|                     observable = Http.instance.head(url, { |                     observable = Http.instance.head(url, { | ||||||
|                         headers: options.headers, |                         headers: angularOptions.headers, | ||||||
|                         observe: 'response', |                         observe: 'response', | ||||||
|                         responseType: <any> options.responseType |                         // eslint-disable-next-line @typescript-eslint/no-explicit-any
 | ||||||
|  |                         responseType: <any> angularOptions.responseType, | ||||||
|                     }); |                     }); | ||||||
|                     break; |                     break; | ||||||
| 
 | 
 | ||||||
|                 default: |                 default: | ||||||
|                     return Promise.reject('Method not implemented yet.'); |                     return Promise.reject(new CoreError('Method not implemented yet.')); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (options.timeout) { |             if (angularOptions.timeout) { | ||||||
|                 observable = observable.pipe(timeout(options.timeout)); |                 observable = observable.pipe(timeout(angularOptions.timeout)); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             return observable.toPromise(); |             return observable.toPromise(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Check if a URL works (it returns a 2XX status). | ||||||
|  |      * | ||||||
|  |      * @param url URL to check. | ||||||
|  |      * @return Promise resolved with boolean: whether it works. | ||||||
|  |      */ | ||||||
|  |     async urlWorks(url: string): Promise<boolean> { | ||||||
|  |         try { | ||||||
|  |             const result = await this.performHead(url); | ||||||
|  | 
 | ||||||
|  |             return result.status >= 200 && result.status < 300; | ||||||
|  |         } catch (error) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export class CoreWS extends makeSingleton(CoreWSProvider) {} | export class CoreWS extends makeSingleton(CoreWSProvider) {} | ||||||
| 
 | 
 | ||||||
| /** |  | ||||||
|  * Error returned by a WS call. |  | ||||||
|  */ |  | ||||||
| export interface CoreWSError { |  | ||||||
|     /** |  | ||||||
|      * The error message. |  | ||||||
|      */ |  | ||||||
|     message: string; |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Name of the exception. Undefined for local errors (fake WS errors). |  | ||||||
|      */ |  | ||||||
|     exception?: string; |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * The error code. Undefined for local errors (fake WS errors). |  | ||||||
|      */ |  | ||||||
|     errorcode?: string; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /** | /** | ||||||
|  * File upload options. |  * File upload options. | ||||||
|  */ |  */ | ||||||
| @ -1084,7 +1053,7 @@ export type CoreWSPreSets = { | |||||||
|      * Defaults to false. Clean multibyte Unicode chars from data. |      * Defaults to false. Clean multibyte Unicode chars from data. | ||||||
|      */ |      */ | ||||||
|     cleanUnicode?: boolean; |     cleanUnicode?: boolean; | ||||||
| } | }; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * PreSets accepted by AJAX WS calls. |  * PreSets accepted by AJAX WS calls. | ||||||
| @ -1109,7 +1078,7 @@ export type CoreWSAjaxPreSets = { | |||||||
|      * Whether to send the parameters via GET. Only if noLogin is true. |      * Whether to send the parameters via GET. Only if noLogin is true. | ||||||
|      */ |      */ | ||||||
|     useGet?: boolean; |     useGet?: boolean; | ||||||
| } | }; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Options for HTTP requests. |  * Options for HTTP requests. | ||||||
| @ -1118,17 +1087,17 @@ export type HttpRequestOptions = { | |||||||
|     /** |     /** | ||||||
|      * The HTTP method. |      * The HTTP method. | ||||||
|      */ |      */ | ||||||
|     method: string; |     method: 'get' | 'post' | 'put' | 'patch' | 'head' | 'delete' | 'options' | 'upload' | 'download'; | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Payload to send to the server. Only applicable on post, put or patch methods. |      * Payload to send to the server. Only applicable on post, put or patch methods. | ||||||
|      */ |      */ | ||||||
|     data?: any; |     data?: Record<string, unknown>; | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Query params to be appended to the URL (only applicable on get, head, delete, upload or download methods). |      * Query params to be appended to the URL (only applicable on get, head, delete, upload or download methods). | ||||||
|      */ |      */ | ||||||
|     params?: any; |     params?: Record<string, string | number>; | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Response type. Defaults to json. |      * Response type. Defaults to json. | ||||||
| @ -1143,7 +1112,7 @@ export type HttpRequestOptions = { | |||||||
|     /** |     /** | ||||||
|      * Serializer to use. Defaults to 'urlencoded'. Only for mobile environments. |      * Serializer to use. Defaults to 'urlencoded'. Only for mobile environments. | ||||||
|      */ |      */ | ||||||
|     serializer?: string; |     serializer?: 'json' | 'urlencoded' | 'utf8' | 'multipart'; | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Whether to follow redirects. Defaults to true. Only for mobile environments. |      * Whether to follow redirects. Defaults to true. Only for mobile environments. | ||||||
| @ -1153,16 +1122,45 @@ export type HttpRequestOptions = { | |||||||
|     /** |     /** | ||||||
|      * Headers. Only for mobile environments. |      * Headers. Only for mobile environments. | ||||||
|      */ |      */ | ||||||
|     headers?: {[name: string]: string}; |     headers?: Record<string, string>; | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * File paths to use for upload or download. Only for mobile environments. |      * File paths to use for upload or download. Only for mobile environments. | ||||||
|      */ |      */ | ||||||
|     filePath?: string; |     filePath?: string | string[]; | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Name to use during upload. Only for mobile environments. |      * Name to use during upload. Only for mobile environments. | ||||||
|      */ |      */ | ||||||
|     name?: string; |     name?: string | string[]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * Options for JSON HTTP requests using Angular Http. | ||||||
|  |  */ | ||||||
|  | type AngularHttpRequestOptions = Omit<HttpRequestOptions, 'data'|'params'> & { | ||||||
|  |     // eslint-disable-next-line @typescript-eslint/no-explicit-any
 | ||||||
|  |     data?: Record<string, any> | string; | ||||||
|  |     params?: HttpParams | { | ||||||
|  |         [param: string]: string | string[]; | ||||||
|  |     }; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Data needed to retry a WS call. | ||||||
|  |  */ | ||||||
|  | type RetryCall = { | ||||||
|  |     method: string; | ||||||
|  |     siteUrl: string; | ||||||
|  |     data: unknown; | ||||||
|  |     preSets: CoreWSPreSets; | ||||||
|  |     deferred: PromiseDefer<unknown>; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Downloaded file entry. It includes some calculated data. | ||||||
|  |  */ | ||||||
|  | export type CoreWSDownloadedFileEntry = FileEntry & { | ||||||
|  |     extension?: string; // File extension.
 | ||||||
|  |     path?: string; // File path.
 | ||||||
|  | }; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user