diff --git a/src/addons/mod/data/components/search/search.ts b/src/addons/mod/data/components/search/search.ts index 69d06f1cc..4221b769a 100644 --- a/src/addons/mod/data/components/search/search.ts +++ b/src/addons/mod/data/components/search/search.ts @@ -71,7 +71,7 @@ export class AddonModDataSearchComponent implements OnInit { this.search.advanced?.forEach((field) => { if (typeof field != 'undefined') { this.advancedIndexed[field.name] = field.value - ? CoreTextUtils.parseJSON(field.value) + ? CoreTextUtils.parseJSON(field.value, '') : ''; } }); diff --git a/src/addons/mod/data/fields/file/services/handler.ts b/src/addons/mod/data/fields/file/services/handler.ts index cdf11047c..016f70c06 100644 --- a/src/addons/mod/data/fields/file/services/handler.ts +++ b/src/addons/mod/data/fields/file/services/handler.ts @@ -112,7 +112,8 @@ export class AddonModDataFieldFileHandlerService implements AddonModDataFieldHan offlineContent: CoreFormFields, offlineFiles?: FileEntry[], ): AddonModDataEntryField { - const uploadedFilesResult: CoreFileUploaderStoreFilesResult = offlineContent?.file; + const uploadedFilesResult: CoreFileUploaderStoreFilesResult | undefined = + offlineContent?.file; if (uploadedFilesResult && uploadedFilesResult.offline > 0 && offlineFiles && offlineFiles?.length > 0) { originalContent.content = offlineFiles[0].name; diff --git a/src/addons/mod/data/fields/latlong/services/handler.ts b/src/addons/mod/data/fields/latlong/services/handler.ts index c55606f22..4eed24cc1 100644 --- a/src/addons/mod/data/fields/latlong/services/handler.ts +++ b/src/addons/mod/data/fields/latlong/services/handler.ts @@ -121,8 +121,8 @@ export class AddonModDataFieldLatlongHandlerService implements AddonModDataField * @inheritdoc */ overrideData(originalContent: AddonModDataEntryField, offlineContent: CoreFormFields): AddonModDataEntryField { - originalContent.content = offlineContent[0] || ''; - originalContent.content1 = offlineContent[1] || ''; + originalContent.content = offlineContent['0'] || ''; + originalContent.content1 = offlineContent['1'] || ''; return originalContent; } diff --git a/src/addons/mod/data/fields/picture/services/handler.ts b/src/addons/mod/data/fields/picture/services/handler.ts index b8a8a89da..d0b503c13 100644 --- a/src/addons/mod/data/fields/picture/services/handler.ts +++ b/src/addons/mod/data/fields/picture/services/handler.ts @@ -155,7 +155,8 @@ export class AddonModDataFieldPictureHandlerService implements AddonModDataField offlineContent: CoreFormFields, offlineFiles?: FileEntry[], ): AddonModDataEntryField { - const uploadedFilesResult: CoreFileUploaderStoreFilesResult = offlineContent?.file; + const uploadedFilesResult: CoreFileUploaderStoreFilesResult | undefined = + offlineContent?.file; if (uploadedFilesResult && uploadedFilesResult.offline > 0 && offlineFiles && offlineFiles?.length > 0) { originalContent.content = offlineFiles[0].name; @@ -165,7 +166,7 @@ export class AddonModDataFieldPictureHandlerService implements AddonModDataField originalContent.files = [uploadedFilesResult.online[0]]; } - originalContent.content1 = offlineContent.alttext || ''; + originalContent.content1 = offlineContent.alttext || ''; return originalContent; } diff --git a/src/addons/mod/data/fields/url/services/handler.ts b/src/addons/mod/data/fields/url/services/handler.ts index 77ecbca8d..ae36f63a5 100644 --- a/src/addons/mod/data/fields/url/services/handler.ts +++ b/src/addons/mod/data/fields/url/services/handler.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { AddonModDataField, AddonModDataSubfieldData } from '@addons/mod/data/services/data'; +import { AddonModDataEntryField, AddonModDataField, AddonModDataSubfieldData } from '@addons/mod/data/services/data'; import { Injectable, Type } from '@angular/core'; import { CoreFormFields } from '@singletons/form'; import { Translate, makeSingleton } from '@singletons'; @@ -59,5 +59,14 @@ export class AddonModDataFieldUrlHandlerService extends AddonModDataFieldTextHan } } + /** + * @inheritdoc + */ + overrideData(originalContent: AddonModDataEntryField, offlineContent: CoreFormFields): AddonModDataEntryField { + originalContent.content = offlineContent['0'] || ''; + + return originalContent; + } + } export const AddonModDataFieldUrlHandler = makeSingleton(AddonModDataFieldUrlHandlerService); diff --git a/src/addons/mod/data/services/data-helper.ts b/src/addons/mod/data/services/data-helper.ts index 9fc836dda..5951a382d 100644 --- a/src/addons/mod/data/services/data-helper.ts +++ b/src/addons/mod/data/services/data-helper.ts @@ -92,9 +92,9 @@ export class AddonModDataHelperProvider { if (offlineContent.subfield) { offlineContents[offlineContent.fieldid][offlineContent.subfield] = - CoreTextUtils.parseJSON(offlineContent.value); + CoreTextUtils.parseJSON(offlineContent.value, ''); } else { - offlineContents[offlineContent.fieldid][''] = CoreTextUtils.parseJSON(offlineContent.value); + offlineContents[offlineContent.fieldid][''] = CoreTextUtils.parseJSON(offlineContent.value, ''); } }); @@ -632,7 +632,7 @@ export class AddonModDataHelperProvider { const folderPath = await AddonModDataOffline.getEntryFieldFolder(dataId, entryId, fieldId, siteId); try { - return CoreFileUploader.getStoredFiles(folderPath); + return await CoreFileUploader.getStoredFiles(folderPath); } catch { // Ignore not found files. return []; diff --git a/src/addons/mod/data/services/data-offline.ts b/src/addons/mod/data/services/data-offline.ts index ffc317d4d..19d8638fe 100644 --- a/src/addons/mod/data/services/data-offline.ts +++ b/src/addons/mod/data/services/data-offline.ts @@ -88,9 +88,9 @@ export class AddonModDataOfflineProvider { const promises: Promise[] = []; entry.fields.forEach((field) => { - const value = CoreTextUtils.parseJSON(field.value); + const value = CoreTextUtils.parseJSON(field.value, null); - if (!value.offline) { + if (!value || !value.offline) { return; } diff --git a/src/addons/mod/data/services/data-sync.ts b/src/addons/mod/data/services/data-sync.ts index 889119427..a010247c4 100644 --- a/src/addons/mod/data/services/data-sync.ts +++ b/src/addons/mod/data/services/data-sync.ts @@ -345,8 +345,8 @@ export class AddonModDataSyncProvider extends CoreCourseActivitySyncBaseProvider try { await Promise.all(editAction.fields.map(async (field) => { // Upload Files if asked. - const value = CoreTextUtils.parseJSON(field.value || ''); - if (value.online || value.offline) { + const value = CoreTextUtils.parseJSON(field.value || '', null); + if (value && (value.online || value.offline)) { let files: CoreFileEntry[] = value.online || []; const offlineFiles = value.offline diff --git a/src/core/services/utils/utils.ts b/src/core/services/utils/utils.ts index 7777cd262..ddf711a7e 100644 --- a/src/core/services/utils/utils.ts +++ b/src/core/services/utils/utils.ts @@ -277,7 +277,10 @@ export class CoreUtilsProvider { return source; } - if (Array.isArray(source)) { + if (this.valueIsFileEntry(source)) { + // Don't clone FileEntry. It has a lot of depth and they shouldn't be modified. + return source; + } else if (Array.isArray(source)) { // Clone the array and all the entries. const newArray = [] as unknown as T; for (let i = 0; i < source.length; i++) { @@ -750,6 +753,18 @@ export class CoreUtilsProvider { return 'isFile' in file; } + /** + * Check if an unknown value is a FileEntry. + * + * @param value Value to check. + * @return Type guard indicating if the file is a FileEntry. + */ + valueIsFileEntry(file: unknown): file is FileEntry { + // We cannot use instanceof because FileEntry is a type. Check some of the properties. + return !!(file && typeof file == 'object' && 'isFile' in file && 'filesystem' in file && + 'toInternalURL' in file && 'copyTo' in file); + } + /** * Check if a value is an object. *