diff --git a/src/addons/block/activitymodules/components/activitymodules/activitymodules.ts b/src/addons/block/activitymodules/components/activitymodules/activitymodules.ts index 1c240c1c6..6b273102d 100644 --- a/src/addons/block/activitymodules/components/activitymodules/activitymodules.ts +++ b/src/addons/block/activitymodules/components/activitymodules/activitymodules.ts @@ -19,7 +19,7 @@ import { CoreBlockBaseComponent } from '@features/block/classes/base-block-compo import { CoreSites } from '@services/sites'; import { ContextLevel, CoreConstants } from '@/core/constants'; import { Translate } from '@singletons'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreObject } from '@singletons/object'; import { CoreNavigator } from '@services/navigator'; import { CoreCourseHelper } from '@features/course/services/course-helper'; import { CoreUrl } from '@singletons/url'; @@ -106,7 +106,7 @@ export class AddonBlockActivityModulesComponent extends CoreBlockBaseComponent i }); // Sort the modnames alphabetically. - modFullNames = CoreUtils.sortValues(modFullNames); + modFullNames = CoreObject.sortValues(modFullNames); for (const modName in modFullNames) { const iconModName = modName === 'resources' ? 'page' : modName; diff --git a/src/addons/blog/services/blog.ts b/src/addons/blog/services/blog.ts index 45b5bb0b7..0a52eceb7 100644 --- a/src/addons/blog/services/blog.ts +++ b/src/addons/blog/services/blog.ts @@ -22,7 +22,7 @@ import { CoreFileEntry, CoreFileHelper } from '@services/file-helper'; import { CoreNetwork } from '@services/network'; import { CoreSites, CoreSitesCommonWSOptions } from '@services/sites'; import { CoreTimeUtils } from '@services/utils/time'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreObject } from '@singletons/object'; import { CoreStatusWithWarningsWSResponse, CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws'; import { makeSingleton } from '@singletons'; import { AddonBlogOffline, AddonBlogOfflineEntry } from './blog-offline'; @@ -63,7 +63,7 @@ export class AddonBlogProvider { * @returns Cache key. */ getEntriesCacheKey(filter: AddonBlogFilter = {}): string { - return ROOT_CACHE_KEY + CoreUtils.sortAndStringify(filter); + return ROOT_CACHE_KEY + CoreObject.sortAndStringify(filter); } /** @@ -77,7 +77,7 @@ export class AddonBlogProvider { const site = await CoreSites.getSite(options?.siteId); const data: CoreBlogGetEntriesWSParams = { - filters: CoreUtils.objectToArrayOfObjects(filter, 'name', 'value'), + filters: CoreObject.toArrayOfObjects(filter, 'name', 'value'), page: options?.page ?? 0, perpage: AddonBlogProvider.ENTRIES_PER_PAGE, }; @@ -290,7 +290,7 @@ export class AddonBlogProvider { const site = await CoreSites.getSite(siteId); const data: AddonBlogViewEntriesWSParams = { - filters: CoreUtils.objectToArrayOfObjects(filter, 'name', 'value'), + filters: CoreObject.toArrayOfObjects(filter, 'name', 'value'), }; return site.write('core_blog_view_entries', data); diff --git a/src/addons/calendar/components/calendar/calendar.ts b/src/addons/calendar/components/calendar/calendar.ts index 419d6b047..46840cabb 100644 --- a/src/addons/calendar/components/calendar/calendar.ts +++ b/src/addons/calendar/components/calendar/calendar.ts @@ -29,7 +29,7 @@ import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreSites } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreTimeUtils } from '@services/utils/time'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreArray } from '@singletons/array'; import { AddonCalendar, AddonCalendarWeek, @@ -464,7 +464,7 @@ class AddonCalendarMonthSlidesItemsManagerSource extends CoreSwipeSlidesDynamicI const categories = await CoreCourses.getCategories(0, true); // Index categories by ID. - this.categories = CoreUtils.arrayToObject(categories, 'id'); + this.categories = CoreArray.toObject(categories, 'id'); } catch { // Ignore errors. } diff --git a/src/addons/calendar/components/filter/filter.ts b/src/addons/calendar/components/filter/filter.ts index 929db0c2c..8bb3aef4d 100644 --- a/src/addons/calendar/components/filter/filter.ts +++ b/src/addons/calendar/components/filter/filter.ts @@ -14,7 +14,7 @@ import { Component, Input, OnInit } from '@angular/core'; import { CoreEnrolledCourseData } from '@features/courses/services/courses'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreObject } from '@singletons/object'; import { ModalController } from '@singletons'; import { CoreEvents } from '@singletons/events'; import { AddonCalendarFilter } from '@addons/calendar/services/calendar-helper'; @@ -54,7 +54,7 @@ export class AddonCalendarFilterComponent implements OnInit { sortedCourses: CoreEnrolledCourseData[] = []; constructor() { - CoreUtils.enumKeys(AddonCalendarEventType).forEach((name) => { + CoreObject.enumKeys(AddonCalendarEventType).forEach((name) => { const value = AddonCalendarEventType[name]; this.typeIcons[value] = AddonCalendarEventIcons[name]; this.types.push(value); diff --git a/src/addons/calendar/pages/day/day.ts b/src/addons/calendar/pages/day/day.ts index bc7039a1c..0c0acf2f7 100644 --- a/src/addons/calendar/pages/day/day.ts +++ b/src/addons/calendar/pages/day/day.ts @@ -33,7 +33,7 @@ import { NgZone, Translate } from '@singletons'; import { CoreNavigator } from '@services/navigator'; import { Params } from '@angular/router'; import { Subscription } from 'rxjs'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreArray } from '@singletons/array'; import { CoreConstants } from '@/core/constants'; import { CoreSwipeSlidesDynamicItemsManager } from '@classes/items-management/swipe-slides-dynamic-items-manager'; import { CoreSwipeSlidesComponent } from '@components/swipe-slides/swipe-slides'; @@ -58,6 +58,7 @@ import { ADDON_CALENDAR_UNDELETED_EVENT_EVENT, AddonCalendarEventType, } from '@addons/calendar/constants'; +import { CoreObject } from '@singletons/object'; /** * Page that displays the calendar events for a certain day. @@ -221,7 +222,7 @@ export class AddonCalendarDayPage implements OnInit, OnDestroy { ngOnInit(): void { const types: string[] = []; - CoreUtils.enumKeys(AddonCalendarEventType).forEach((name) => { + CoreObject.enumKeys(AddonCalendarEventType).forEach((name) => { const value = AddonCalendarEventType[name]; this.filter[name] = CoreNavigator.getRouteBooleanParam(name) ?? true; types.push(value); @@ -606,7 +607,7 @@ class AddonCalendarDaySlidesItemsManagerSource extends CoreSwipeSlidesDynamicIte const categories = await CoreCourses.getCategories(0, true); // Index categories by ID. - this.categories = CoreUtils.arrayToObject(categories, 'id'); + this.categories = CoreArray.toObject(categories, 'id'); } catch { // Ignore errors. } diff --git a/src/addons/calendar/services/calendar-helper.ts b/src/addons/calendar/services/calendar-helper.ts index 5299901e8..decb8075e 100644 --- a/src/addons/calendar/services/calendar-helper.ts +++ b/src/addons/calendar/services/calendar-helper.ts @@ -25,7 +25,7 @@ import { AddonCalendarWeekDay, } from './calendar'; import { CoreConfig } from '@services/config'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreObject } from '@singletons/object'; import { CoreCourse } from '@features/course/services/course'; import { ContextLevel, CoreConstants } from '@/core/constants'; import moment from 'moment-timezone'; @@ -61,7 +61,7 @@ export class AddonCalendarHelperProvider { */ getEventIcon(eventType: AddonCalendarEventType | string): string { if (this.eventTypeIcons.length == 0) { - CoreUtils.enumKeys(AddonCalendarEventType).forEach((name) => { + CoreObject.enumKeys(AddonCalendarEventType).forEach((name) => { const value = AddonCalendarEventType[name]; this.eventTypeIcons[value] = AddonCalendarEventIcons[name]; }); diff --git a/src/addons/calendar/services/calendar-offline.ts b/src/addons/calendar/services/calendar-offline.ts index 4136fa66f..0af703c16 100644 --- a/src/addons/calendar/services/calendar-offline.ts +++ b/src/addons/calendar/services/calendar-offline.ts @@ -15,7 +15,7 @@ import { Injectable } from '@angular/core'; import { SQLiteDBRecordValues } from '@classes/sqlitedb'; import { CoreSites } from '@services/sites'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreArray } from '@singletons/array'; import { makeSingleton } from '@singletons'; import { AddonCalendarSubmitCreateUpdateFormDataWSParams } from './calendar'; import { @@ -62,7 +62,7 @@ export class AddonCalendarOfflineProvider { const result = await Promise.all(promises); - return CoreUtils.mergeArraysWithoutDuplicates(result[0], result[1]); + return CoreArray.mergeWithoutDuplicates(result[0], result[1]); } /** diff --git a/src/addons/calendar/services/calendar.ts b/src/addons/calendar/services/calendar.ts index 00e9d623e..2930eba52 100644 --- a/src/addons/calendar/services/calendar.ts +++ b/src/addons/calendar/services/calendar.ts @@ -19,7 +19,7 @@ import { CoreNetwork } from '@services/network'; import { CoreText } from '@singletons/text'; import { CoreTimeUtils } from '@services/utils/time'; import { CoreUrl } from '@singletons/url'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreObject } from '@singletons/object'; import { CoreGroups } from '@services/groups'; import { CoreLocalNotifications } from '@services/local-notifications'; import { CoreConfig } from '@services/config'; @@ -1578,7 +1578,7 @@ export class AddonCalendarProvider { } const params: AddonCalendarSubmitCreateUpdateFormWSParams = { - formdata: CoreUtils.objectToGetParams(formData), + formdata: CoreObject.toGetParams(formData), }; const result = await site.write('core_calendar_submit_create_update_form', params); diff --git a/src/addons/mod/assign/services/assign-helper.ts b/src/addons/mod/assign/services/assign-helper.ts index 296611d17..0b197f99d 100644 --- a/src/addons/mod/assign/services/assign-helper.ts +++ b/src/addons/mod/assign/services/assign-helper.ts @@ -27,7 +27,7 @@ import { AddonModAssignSubmissionStatusValues, } from './assign'; import { AddonModAssignOffline } from './assign-offline'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreObject } from '@singletons/object'; import { CoreFile } from '@services/file'; import { CoreCourseCommonModWSOptions } from '@features/course/services/course'; import { CoreGroups } from '@services/groups'; @@ -314,7 +314,7 @@ export class AddonModAssignHelperProvider { await Promise.all(promises); - return CoreUtils.objectToArray(participantsIndexed); + return CoreObject.toArray(participantsIndexed); } /** diff --git a/src/addons/mod/bigbluebuttonbn/components/index/index.ts b/src/addons/mod/bigbluebuttonbn/components/index/index.ts index 36498b7dc..e17df7e76 100644 --- a/src/addons/mod/bigbluebuttonbn/components/index/index.ts +++ b/src/addons/mod/bigbluebuttonbn/components/index/index.ts @@ -23,7 +23,7 @@ import { CoreSites } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreText } from '@singletons/text'; import { CoreTimeUtils } from '@services/utils/time'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreArray } from '@singletons/array'; import { Translate } from '@singletons'; import { AddonModBBB, @@ -146,7 +146,7 @@ export class AddonModBBBIndexComponent extends CoreCourseModuleMainActivityCompo const recordingsTable = await AddonModBBB.getRecordings(this.bbb.id, this.groupId, { cmId: this.module.id, }); - const columns = CoreUtils.arrayToObject(recordingsTable.columns, 'key'); + const columns = CoreArray.toObject(recordingsTable.columns, 'key'); this.recordings = recordingsTable.parsedData.map(recordingData => { const details: RecordingDetail[] = []; diff --git a/src/addons/mod/bigbluebuttonbn/services/bigbluebuttonbn.ts b/src/addons/mod/bigbluebuttonbn/services/bigbluebuttonbn.ts index 58c7e3ca4..0b8381780 100644 --- a/src/addons/mod/bigbluebuttonbn/services/bigbluebuttonbn.ts +++ b/src/addons/mod/bigbluebuttonbn/services/bigbluebuttonbn.ts @@ -20,7 +20,7 @@ import { CoreCourseCommonModWSOptions } from '@features/course/services/course'; import { CoreCourseLogHelper } from '@features/course/services/log-helper'; import { CoreSites, CoreSitesCommonWSOptions } from '@services/sites'; import { CoreText } from '@singletons/text'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreObject } from '@singletons/object'; import { CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws'; import { makeSingleton, Translate } from '@singletons'; import { ADDON_MOD_BBB_COMPONENT } from '../constants'; @@ -182,7 +182,7 @@ export class AddonModBBBService { return { ...meetingInfo, - features: meetingInfo.features ? CoreUtils.objectToKeyValueMap(meetingInfo.features, 'name', 'isenabled') : undefined, + features: meetingInfo.features ? CoreObject.toKeyValueMap(meetingInfo.features, 'name', 'isenabled') : undefined, }; } diff --git a/src/addons/mod/data/components/index/index.ts b/src/addons/mod/data/components/index/index.ts index 0265b0635..92a4e4489 100644 --- a/src/addons/mod/data/components/index/index.ts +++ b/src/addons/mod/data/components/index/index.ts @@ -26,7 +26,7 @@ import { CoreNavigator } from '@services/navigator'; import { CoreSites } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreTimeUtils } from '@services/utils/time'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreArray } from '@singletons/array'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { AddonModData, @@ -53,6 +53,7 @@ import { } from '../../constants'; import { CoreModals } from '@services/modals'; import { CorePromiseUtils } from '@singletons/promise-utils'; +import { CoreObject } from '@singletons/object'; const contentToken = ''; @@ -269,8 +270,8 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp const fields = await AddonModData.getFields(this.database.id, { cmId: this.module.id }); this.search.advanced = []; - this.fields = CoreUtils.arrayToObject(fields, 'id'); - this.fieldsArray = CoreUtils.objectToArray(this.fields); + this.fields = CoreArray.toObject(fields, 'id'); + this.fieldsArray = CoreObject.toArray(this.fields); if (this.fieldsArray.length == 0) { canSearch = false; canAdd = false; diff --git a/src/addons/mod/data/components/search-modal/search-modal.ts b/src/addons/mod/data/components/search-modal/search-modal.ts index 993563ea0..2fe023190 100644 --- a/src/addons/mod/data/components/search-modal/search-modal.ts +++ b/src/addons/mod/data/components/search-modal/search-modal.ts @@ -18,7 +18,7 @@ import { CoreTag } from '@features/tag/services/tag'; import { CoreSites } from '@services/sites'; import { CoreFormFields, CoreForms } from '@singletons/form'; import { CoreText } from '@singletons/text'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreObject } from '@singletons/object'; import { ModalController } from '@singletons'; import { AddonModDataField, @@ -89,7 +89,7 @@ export class AddonModDataSearchModalComponent implements OnInit { this.searchForm.addControl('firstname', this.fb.control(this.advancedIndexed['firstname'] || '')); this.searchForm.addControl('lastname', this.fb.control(this.advancedIndexed['lastname'] || '')); - this.fieldsArray = CoreUtils.objectToArray(this.fields); + this.fieldsArray = CoreObject.toArray(this.fields); this.advancedSearch = this.renderAdvancedSearchFields(); } diff --git a/src/addons/mod/data/pages/edit/edit.ts b/src/addons/mod/data/pages/edit/edit.ts index 3394b93fb..87856bbe4 100644 --- a/src/addons/mod/data/pages/edit/edit.ts +++ b/src/addons/mod/data/pages/edit/edit.ts @@ -46,6 +46,7 @@ import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics'; import { ADDON_MOD_DATA_COMPONENT, ADDON_MOD_DATA_ENTRY_CHANGED, AddonModDataTemplateType } from '../../constants'; import { CoreLoadings } from '@services/loadings'; import { CoreWSError } from '@classes/errors/wserror'; +import { CoreArray } from '@singletons/array'; /** * Page that displays the view edit page. @@ -180,7 +181,7 @@ export class AddonModDataEditPage implements OnInit { this.cssClass = 'addon-data-entries-' + this.database.id; this.fieldsArray = await AddonModData.getFields(this.database.id, { cmId: this.moduleId }); - this.fields = CoreUtils.arrayToObject(this.fieldsArray, 'id'); + this.fields = CoreArray.toObject(this.fieldsArray, 'id'); const entry = await AddonModDataHelper.fetchEntry(this.database, this.fieldsArray, this.entryId || 0); this.entry = entry.entry; diff --git a/src/addons/mod/data/pages/entry/entry.ts b/src/addons/mod/data/pages/entry/entry.ts index 82844859e..4991ebf63 100644 --- a/src/addons/mod/data/pages/entry/entry.ts +++ b/src/addons/mod/data/pages/entry/entry.ts @@ -22,7 +22,7 @@ import { CoreGroups, CoreGroupInfo } from '@services/groups'; import { CoreNavigator } from '@services/navigator'; import { CoreSites } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreArray } from '@singletons/array'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { AddonModDataComponentsCompileModule } from '../../components/components-compile.module'; import { @@ -183,7 +183,7 @@ export class AddonModDataEntryPage implements OnInit, OnDestroy { this.title = this.database.name || this.title; this.fieldsArray = await AddonModData.getFields(this.database.id, { cmId: this.moduleId }); - this.fields = CoreUtils.arrayToObject(this.fieldsArray, 'id'); + this.fields = CoreArray.toObject(this.fieldsArray, 'id'); await this.setEntryFromOffset(); diff --git a/src/addons/mod/data/services/data-sync.ts b/src/addons/mod/data/services/data-sync.ts index 7f7884cf2..dba2f6dc8 100644 --- a/src/addons/mod/data/services/data-sync.ts +++ b/src/addons/mod/data/services/data-sync.ts @@ -26,7 +26,7 @@ import { CoreFileEntry } from '@services/file-helper'; import { CoreSites, CoreSitesReadingStrategy } from '@services/sites'; import { CoreSync, CoreSyncResult } from '@services/sync'; import { CoreErrorHelper } from '@services/error-helper'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreObject } from '@singletons/object'; import { Translate, makeSingleton } from '@singletons'; import { CoreEvents } from '@singletons/events'; import { AddonModData, AddonModDataData } from './data'; @@ -206,7 +206,7 @@ export class AddonModDataSyncProvider extends CoreCourseActivitySyncBaseProvider offlineEntries[entry.entryid].push(entry); }); - const promises = CoreUtils.objectToArray(offlineEntries).map((entryActions) => + const promises = CoreObject.toArray(offlineEntries).map((entryActions) => this.syncEntry(database, entryActions, result, siteId)); await Promise.all(promises); diff --git a/src/addons/mod/data/services/data.ts b/src/addons/mod/data/services/data.ts index 1ba6d875d..ce0823581 100644 --- a/src/addons/mod/data/services/data.ts +++ b/src/addons/mod/data/services/data.ts @@ -22,7 +22,7 @@ import { CoreNetwork } from '@services/network'; import { CoreFileEntry } from '@services/file-helper'; import { CoreFilepool } from '@services/filepool'; import { CoreSites, CoreSitesCommonWSOptions, CoreSitesReadingStrategy } from '@services/sites'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreArray } from '@singletons/array'; import { CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws'; import { makeSingleton, Translate } from '@singletons'; import { AddonModDataFieldsDelegate } from './data-fields-delegate'; @@ -251,7 +251,7 @@ export class AddonModDataProvider { */ protected checkFields(fields: AddonModDataField[], contents: AddonModDataSubfieldData[]): AddonModDataFieldNotification[] { const notifications: AddonModDataFieldNotification[] = []; - const contentsIndexed = CoreUtils.arrayToObjectMultiple(contents, 'fieldid'); + const contentsIndexed = CoreArray.toObjectMultiple(contents, 'fieldid'); // App is offline, check required fields. fields.forEach((field) => { @@ -741,7 +741,7 @@ export class AddonModDataProvider { */ protected formatEntryContents(entry: AddonModDataEntryWS): AddonModDataEntry { return Object.assign(entry, { - contents: CoreUtils.arrayToObject(entry.contents, 'fieldid'), + contents: CoreArray.toObject(entry.contents, 'fieldid'), }); } diff --git a/src/addons/mod/data/services/handlers/prefetch-lazy.ts b/src/addons/mod/data/services/handlers/prefetch-lazy.ts index a185d7e05..27621eb08 100644 --- a/src/addons/mod/data/services/handlers/prefetch-lazy.ts +++ b/src/addons/mod/data/services/handlers/prefetch-lazy.ts @@ -20,7 +20,7 @@ import { CoreFilepool } from '@services/filepool'; import { CoreGroup, CoreGroups } from '@services/groups'; import { CoreSitesCommonWSOptions, CoreSites, CoreSitesReadingStrategy } from '@services/sites'; import { CoreTimeUtils } from '@services/utils/time'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreObject } from '@singletons/object'; import { CoreWSFile } from '@services/ws'; import { makeSingleton } from '@singletons'; import { AddonModDataEntry, AddonModData, AddonModDataData } from '../data'; @@ -63,7 +63,7 @@ export class AddonModDataPrefetchHandlerLazyService extends AddonModDataPrefetch }); }); - return CoreUtils.objectToArray(uniqueEntries); + return CoreObject.toArray(uniqueEntries); } /** @@ -133,7 +133,7 @@ export class AddonModDataPrefetchHandlerLazyService extends AddonModDataPrefetch let files: CoreWSFile[] = []; entries.forEach((entry) => { - CoreUtils.objectToArray(entry.contents).forEach((content) => { + CoreObject.toArray(entry.contents).forEach((content) => { files = files.concat(content.files); }); }); diff --git a/src/addons/mod/feedback/pages/form/form.ts b/src/addons/mod/feedback/pages/form/form.ts index 16b54cac0..e4d45815b 100644 --- a/src/addons/mod/feedback/pages/form/form.ts +++ b/src/addons/mod/feedback/pages/form/form.ts @@ -46,6 +46,7 @@ import { CoreLoadings } from '@services/loadings'; import { CoreError } from '@classes/errors/error'; import { CorePromiseUtils } from '@singletons/promise-utils'; import { CoreWSError } from '@classes/errors/wserror'; +import { CoreObject } from '@singletons/object'; /** * Page that displays feedback form. @@ -158,7 +159,7 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave { if (this.items && !this.completed && this.originalData) { // Form submitted. Check if there is any change. - if (!CoreUtils.basicLeftCompare(responses, this.originalData, 3)) { + if (!CoreObject.basicLeftCompare(responses, this.originalData, 3)) { await CoreDomUtils.showConfirm(Translate.instant('core.confirmcanceledit')); } } diff --git a/src/addons/mod/feedback/services/feedback.ts b/src/addons/mod/feedback/services/feedback.ts index a01b4e90e..f89a6a3ed 100644 --- a/src/addons/mod/feedback/services/feedback.ts +++ b/src/addons/mod/feedback/services/feedback.ts @@ -19,7 +19,7 @@ import { CoreCourseLogHelper } from '@features/course/services/log-helper'; import { CoreNetwork } from '@services/network'; import { CoreFilepool } from '@services/filepool'; import { CoreSites, CoreSitesCommonWSOptions, CoreSitesReadingStrategy } from '@services/sites'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreObject } from '@singletons/object'; import { CoreWSExternalFile, CoreWSExternalWarning, CoreWSStoredFile } from '@services/ws'; import { makeSingleton, Translate } from '@singletons'; import { AddonModFeedbackOffline } from './feedback-offline'; @@ -170,7 +170,7 @@ export class AddonModFeedbackProvider { // Merge all values into one array. const offlineValuesArray = offlineResponses.reduce((array, entry) => { - const responses = CoreUtils.objectToArrayOfObjects(entry.responses, 'id', 'value'); + const responses = CoreObject.toArrayOfObjects(entry.responses, 'id', 'value'); return array.concat(responses); }, []).map((valueEntry) => { @@ -1228,7 +1228,7 @@ export class AddonModFeedbackProvider { const params: AddonModFeedbackProcessPageWSParams = { feedbackid: feedbackId, page: page, - responses: CoreUtils.objectToArrayOfObjects(responses, 'name', 'value'), + responses: CoreObject.toArrayOfObjects(responses, 'name', 'value'), goprevious: goPrevious, }; diff --git a/src/addons/mod/forum/pages/discussion/discussion.ts b/src/addons/mod/forum/pages/discussion/discussion.ts index a5aa68859..bafd3b355 100644 --- a/src/addons/mod/forum/pages/discussion/discussion.ts +++ b/src/addons/mod/forum/pages/discussion/discussion.ts @@ -63,6 +63,7 @@ import { CoreCourseContentsPage } from '@features/course/pages/contents/contents import { CoreToasts } from '@services/toasts'; import { CoreLoadings } from '@services/loadings'; import { CorePromiseUtils } from '@singletons/promise-utils'; +import { CoreObject } from '@singletons/object'; type SortType = 'flat-newest' | 'flat-oldest' | 'nested'; @@ -463,7 +464,7 @@ export class AddonModForumDiscussionPage implements OnInit, AfterViewInit, OnDes await Promise.all(convertPromises); // Convert back to array. - onlinePosts = CoreUtils.objectToArray(onlinePostsMap); + onlinePosts = CoreObject.toArray(onlinePostsMap); let posts = offlineReplies.concat(onlinePosts); diff --git a/src/addons/mod/forum/services/forum.ts b/src/addons/mod/forum/services/forum.ts index e933b4eee..12e9958e2 100644 --- a/src/addons/mod/forum/services/forum.ts +++ b/src/addons/mod/forum/services/forum.ts @@ -52,6 +52,7 @@ import { import { CoreCacheUpdateFrequency } from '@/core/constants'; import { CorePromiseUtils } from '@singletons/promise-utils'; import { CoreWSError } from '@classes/errors/wserror'; +import { CoreObject } from '@singletons/object'; declare module '@singletons/events' { @@ -221,7 +222,7 @@ export class AddonModForumProvider { message: message, // eslint-disable-next-line max-len - options: CoreUtils.objectToArrayOfObjects( + options: CoreObject.toArrayOfObjects( options || {}, 'name', 'value', @@ -1147,7 +1148,7 @@ export class AddonModForumProvider { subject: subject, message: message, - options: CoreUtils.objectToArrayOfObjects< + options: CoreObject.toArrayOfObjects< AddonModForumAddDiscussionPostWSOptionsArray[0], AddonModForumAddDiscussionPostWSOptionsObject >( @@ -1277,7 +1278,7 @@ export class AddonModForumProvider { } }); - CoreUser.storeUsers(CoreUtils.objectToArray(users)); + CoreUser.storeUsers(CoreObject.toArray(users)); } /** @@ -1332,7 +1333,7 @@ export class AddonModForumProvider { subject: subject, message: message, - options: CoreUtils.objectToArrayOfObjects< + options: CoreObject.toArrayOfObjects< AddonModForumUpdateDiscussionPostWSOptionsArray[0], AddonModForumUpdateDiscussionPostWSOptionsObject >( diff --git a/src/addons/mod/glossary/services/glossary.ts b/src/addons/mod/glossary/services/glossary.ts index 8e04dfc6c..fc204b34e 100644 --- a/src/addons/mod/glossary/services/glossary.ts +++ b/src/addons/mod/glossary/services/glossary.ts @@ -22,7 +22,7 @@ import { CoreRatingInfo } from '@features/rating/services/rating'; import { CoreTagItem } from '@features/tag/services/tag'; import { CoreNetwork } from '@services/network'; import { CoreSites, CoreSitesCommonWSOptions, CoreSitesReadingStrategy } from '@services/sites'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreObject } from '@singletons/object'; import { CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws'; import { makeSingleton, Translate } from '@singletons'; import { CoreEvents } from '@singletons/events'; @@ -911,7 +911,7 @@ export class AddonModGlossaryProvider { concept: concept, definition: definition, definitionformat: 1, - options: CoreUtils.objectToArrayOfObjects(options || {}, 'name', 'value'), + options: CoreObject.toArrayOfObjects(options || {}, 'name', 'value'), }; if (attachId) { @@ -955,7 +955,7 @@ export class AddonModGlossaryProvider { concept: concept, definition: definition, definitionformat: 1, - options: CoreUtils.objectToArrayOfObjects(options || {}, 'name', 'value'), + options: CoreObject.toArrayOfObjects(options || {}, 'name', 'value'), }; if (attachId) { diff --git a/src/addons/mod/lesson/pages/player/player.ts b/src/addons/mod/lesson/pages/player/player.ts index 328921c0d..012540ae2 100644 --- a/src/addons/mod/lesson/pages/player/player.ts +++ b/src/addons/mod/lesson/pages/player/player.ts @@ -24,7 +24,7 @@ import { CoreSites, CoreSitesCommonWSOptions, CoreSitesReadingStrategy } from '@ import { CoreSync } from '@services/sync'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreUrl } from '@singletons/url'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreObject } from '@singletons/object'; import { CoreWSExternalFile } from '@services/ws'; import { ModalController, Translate } from '@singletons'; import { CoreEvents } from '@singletons/events'; @@ -171,7 +171,7 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy, CanLeave { if (this.question && !this.eolData && !this.processData && this.originalData) { // Question shown. Check if there is any change. - if (!CoreUtils.basicLeftCompare(this.questionForm.getRawValue(), this.originalData, 3)) { + if (!CoreObject.basicLeftCompare(this.questionForm.getRawValue(), this.originalData, 3)) { await CoreDomUtils.showConfirm(Translate.instant('core.confirmcanceledit')); } } diff --git a/src/addons/mod/lesson/services/lesson-offline.ts b/src/addons/mod/lesson/services/lesson-offline.ts index b7cd842cf..eb1659fd0 100644 --- a/src/addons/mod/lesson/services/lesson-offline.ts +++ b/src/addons/mod/lesson/services/lesson-offline.ts @@ -17,7 +17,7 @@ import { CoreSites } from '@services/sites'; import { CoreFormFields } from '@singletons/form'; import { CoreText } from '@singletons/text'; import { CoreTimeUtils } from '@services/utils/time'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreObject } from '@singletons/object'; import { makeSingleton } from '@singletons'; import { AddonModLessonPageAttemptDBRecord, @@ -152,7 +152,7 @@ export class AddonModLessonOfflineProvider { this.getLessonsFromEntries(lessons, pageAttempts || []); this.getLessonsFromEntries(lessons, retakes || []); - return CoreUtils.objectToArray(lessons); + return CoreObject.toArray(lessons); } /** diff --git a/src/addons/mod/lesson/services/lesson.ts b/src/addons/mod/lesson/services/lesson.ts index ddb6340e9..f20f3ae44 100644 --- a/src/addons/mod/lesson/services/lesson.ts +++ b/src/addons/mod/lesson/services/lesson.ts @@ -37,6 +37,8 @@ import { import { CoreGradeType } from '@features/grades/constants'; import { CoreCacheUpdateFrequency } from '@/core/constants'; import { CorePromiseUtils } from '@singletons/promise-utils'; +import { CoreObject } from '@singletons/object'; +import { CoreArray } from '@singletons/array'; declare module '@singletons/events' { @@ -286,7 +288,7 @@ export class AddonModLessonProvider { const validPages = {}; let pageId = accessInfo.firstpageid; - viewedPagesIds = CoreUtils.mergeArraysWithoutDuplicates(viewedPagesIds, viewedContentPagesIds); + viewedPagesIds = CoreArray.mergeWithoutDuplicates(viewedPagesIds, viewedContentPagesIds); // Filter out the following pages: // - End of Cluster @@ -398,11 +400,11 @@ export class AddonModLessonProvider { // The name was changed to "answer_editor" in 3.7. Before it was just "answer". Support both cases. if (data['answer_editor[text]'] !== undefined) { studentAnswer = data['answer_editor[text]']; - } else if (typeof data.answer_editor == 'object') { + } else if (typeof data.answer_editor === 'object') { studentAnswer = (<{text: string}> data.answer_editor).text; } else if (data['answer[text]'] !== undefined) { studentAnswer = data['answer[text]']; - } else if (typeof data.answer == 'object') { + } else if (typeof data.answer === 'object') { studentAnswer = (<{text: string}> data.answer).text; } else { studentAnswer = data.answer; @@ -3087,7 +3089,7 @@ export class AddonModLessonProvider { const params: AddonModLessonProcessPageWSParams = { lessonid: lessonId, pageid: pageId, - data: CoreUtils.objectToArrayOfObjects(data, 'name', 'value', true), + data: CoreObject.toArrayOfObjects(data, 'name', 'value', true), review: !!options.review, }; diff --git a/src/addons/mod/quiz/services/quiz.ts b/src/addons/mod/quiz/services/quiz.ts index 77891551c..98a3e06e3 100644 --- a/src/addons/mod/quiz/services/quiz.ts +++ b/src/addons/mod/quiz/services/quiz.ts @@ -53,6 +53,8 @@ import { } from '../constants'; import { CoreIonicColorNames } from '@singletons/colors'; import { CoreCacheUpdateFrequency } from '@/core/constants'; +import { CoreObject } from '@singletons/object'; +import { CoreArray } from '@singletons/array'; declare module '@singletons/events' { @@ -227,7 +229,7 @@ export class AddonModQuizProvider { const params: AddonModQuizGetAttemptDataWSParams = { attemptid: attemptId, page: page, - preflightdata: CoreUtils.objectToArrayOfObjects( + preflightdata: CoreObject.toArrayOfObjects( preflightData, 'name', 'value', @@ -550,7 +552,7 @@ export class AddonModQuizProvider { const params: AddonModQuizGetAttemptSummaryWSParams = { attemptid: attemptId, - preflightdata: CoreUtils.objectToArrayOfObjects( + preflightdata: CoreObject.toArrayOfObjects( preflightData, 'name', 'value', @@ -629,8 +631,8 @@ export class AddonModQuizProvider { // Convert the arrays to objects with name -> value. return { - someoptions: > CoreUtils.objectToKeyValueMap(response.someoptions, 'name', 'value'), - alloptions: > CoreUtils.objectToKeyValueMap(response.alloptions, 'name', 'value'), + someoptions: > CoreObject.toKeyValueMap(response.someoptions, 'name', 'value'), + alloptions: > CoreObject.toKeyValueMap(response.alloptions, 'name', 'value'), warnings: response.warnings, }; } @@ -1640,7 +1642,7 @@ export class AddonModQuizProvider { const params: AddonModQuizViewAttemptWSParams = { attemptid: attemptId, page: page, - preflightdata: CoreUtils.objectToArrayOfObjects( + preflightdata: CoreObject.toArrayOfObjects( preflightData, 'name', 'value', @@ -1695,7 +1697,7 @@ export class AddonModQuizProvider { ): Promise { const params: AddonModQuizViewAttemptSummaryWSParams = { attemptid: attemptId, - preflightdata: CoreUtils.objectToArrayOfObjects( + preflightdata: CoreObject.toArrayOfObjects( preflightData, 'name', 'value', @@ -1785,10 +1787,10 @@ export class AddonModQuizProvider { const params: AddonModQuizProcessAttemptWSParams = { attemptid: attemptId, - data: CoreUtils.objectToArrayOfObjects(data, 'name', 'value'), + data: CoreObject.toArrayOfObjects(data, 'name', 'value'), finishattempt: !!finish, timeup: !!timeUp, - preflightdata: CoreUtils.objectToArrayOfObjects( + preflightdata: CoreObject.toArrayOfObjects( preflightData, 'name', 'value', @@ -1834,7 +1836,7 @@ export class AddonModQuizProvider { }); // Convert the question array to an object. - const questions = CoreUtils.arrayToObject(questionsArray, 'slot'); + const questions = CoreArray.toObject(questionsArray, 'slot'); return AddonModQuizOffline.processAttempt(quiz, attempt, questions, data, finish, siteId); } @@ -1939,8 +1941,8 @@ export class AddonModQuizProvider { const params: AddonModQuizSaveAttemptWSParams = { attemptid: attemptId, - data: CoreUtils.objectToArrayOfObjects(data, 'name', 'value'), - preflightdata: CoreUtils.objectToArrayOfObjects( + data: CoreObject.toArrayOfObjects(data, 'name', 'value'), + preflightdata: CoreObject.toArrayOfObjects( preflightData, 'name', 'value', @@ -1995,7 +1997,7 @@ export class AddonModQuizProvider { const params: AddonModQuizStartAttemptWSParams = { quizid: quizId, - preflightdata: CoreUtils.objectToArrayOfObjects( + preflightdata: CoreObject.toArrayOfObjects( preflightData, 'name', 'value', diff --git a/src/addons/mod/scorm/components/index/index.ts b/src/addons/mod/scorm/components/index/index.ts index 15ce952c3..93d8d1da3 100644 --- a/src/addons/mod/scorm/components/index/index.ts +++ b/src/addons/mod/scorm/components/index/index.ts @@ -22,7 +22,7 @@ import { IonContent } from '@ionic/angular'; import { CoreNavigator } from '@services/navigator'; import { CoreSync } from '@services/sync'; import { CoreDomUtils } from '@services/utils/dom'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreObject } from '@singletons/object'; import { Translate } from '@singletons'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { AddonModScormPrefetchHandler } from '../../services/handlers/prefetch'; @@ -340,8 +340,8 @@ export class AddonModScormIndexComponent extends CoreCourseModuleMainActivityCom this.grade = AddonModScorm.calculateScormGrade(scorm, onlineAttempts); // Add the attempts to the SCORM in array format in ASC order, and format the grades. - this.onlineAttempts = CoreUtils.objectToArray(onlineAttempts); - this.offlineAttempts = CoreUtils.objectToArray(offlineAttempts); + this.onlineAttempts = CoreObject.toArray(onlineAttempts); + this.offlineAttempts = CoreObject.toArray(offlineAttempts); this.onlineAttempts.sort((a, b) => a.num - b.num); this.offlineAttempts.sort((a, b) => a.num - b.num); diff --git a/src/addons/mod/scorm/services/scorm.ts b/src/addons/mod/scorm/services/scorm.ts index bdd236bbb..585c5f1e8 100644 --- a/src/addons/mod/scorm/services/scorm.ts +++ b/src/addons/mod/scorm/services/scorm.ts @@ -23,7 +23,7 @@ import { CoreSync } from '@services/sync'; import { CoreText } from '@singletons/text'; import { CoreTimeUtils } from '@services/utils/time'; import { CoreUrl } from '@singletons/url'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreObject } from '@singletons/object'; import { CoreWS, CoreWSExternalFile, CoreWSExternalWarning, CoreWSFile, CoreWSPreSets } from '@services/ws'; import { makeSingleton, Translate } from '@singletons'; import { CoreEvents } from '@singletons/events'; @@ -808,12 +808,12 @@ export class AddonModScormProvider { response.data.forEach((sco) => { data[sco.scoid] = { scoid: sco.scoid, - defaultdata: > CoreUtils.objectToKeyValueMap( + defaultdata: > CoreObject.toKeyValueMap( sco.defaultdata, 'element', 'value', ), - userdata: > CoreUtils.objectToKeyValueMap(sco.userdata, 'element', 'value'), + userdata: > CoreObject.toKeyValueMap(sco.userdata, 'element', 'value'), }; }); @@ -1114,7 +1114,7 @@ export class AddonModScormProvider { } if (response.options) { - const scormOptions = CoreUtils.objectToKeyValueMap(response.options, 'name', 'value'); + const scormOptions = CoreObject.toKeyValueMap(response.options, 'name', 'value'); if (scormOptions.scormstandard) { currentScorm.scormStandard = Number(scormOptions.scormstandard); diff --git a/src/addons/mod/workshop/components/assessment-strategy/assessment-strategy.ts b/src/addons/mod/workshop/components/assessment-strategy/assessment-strategy.ts index 982b56aab..2834b706e 100644 --- a/src/addons/mod/workshop/components/assessment-strategy/assessment-strategy.ts +++ b/src/addons/mod/workshop/components/assessment-strategy/assessment-strategy.ts @@ -45,6 +45,7 @@ import { toBoolean } from '@/core/transforms/boolean'; import { CoreLoadings } from '@services/loadings'; import { CorePromiseUtils } from '@singletons/promise-utils'; import { CoreWSError } from '@classes/errors/wserror'; +import { CoreObject } from '@singletons/object'; /** * Component that displays workshop assessment strategy form. @@ -188,7 +189,7 @@ export class AddonModWorkshopAssessmentStrategyComponent implements OnInit, OnDe // Override assessment plugins values. this.data.assessment.form.current = AddonModWorkshop.parseFields( - CoreUtils.objectToArrayOfObjects(offlineData, 'name', 'value'), + CoreObject.toArrayOfObjects(offlineData, 'name', 'value'), ); // Override offline files. diff --git a/src/addons/mod/workshop/components/index/index.ts b/src/addons/mod/workshop/components/index/index.ts index 38cb33567..20e3d6346 100644 --- a/src/addons/mod/workshop/components/index/index.ts +++ b/src/addons/mod/workshop/components/index/index.ts @@ -22,7 +22,7 @@ import { CoreGroupInfo, CoreGroups } from '@services/groups'; import { CoreNavigator } from '@services/navigator'; import { CorePlatform } from '@services/platform'; import { CoreModals } from '@services/modals'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreObject } from '@singletons/object'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { Subscription } from 'rxjs'; import { @@ -405,7 +405,7 @@ export class AddonModWorkshopIndexComponent extends CoreCourseModuleMainActivity const modalData = await CoreModals.openModal({ component: AddonModWorkshopPhaseInfoModalComponent, componentProps: { - phases: CoreUtils.objectToArray(this.phases), + phases: CoreObject.toArray(this.phases), workshopPhase: this.workshop.phase, externalUrl: this.module.url, showSubmit: this.showSubmit, diff --git a/src/addons/mod/workshop/services/handlers/prefetch-lazy.ts b/src/addons/mod/workshop/services/handlers/prefetch-lazy.ts index d31b1492b..a0b9de9f9 100644 --- a/src/addons/mod/workshop/services/handlers/prefetch-lazy.ts +++ b/src/addons/mod/workshop/services/handlers/prefetch-lazy.ts @@ -20,7 +20,7 @@ import { CoreUser } from '@features/user/services/user'; import { CoreFilepool } from '@services/filepool'; import { CoreGroup, CoreGroups } from '@services/groups'; import { CoreSites, CoreSitesReadingStrategy, CoreSitesCommonWSOptions } from '@services/sites'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreObject } from '@singletons/object'; import { CoreWSExternalFile, CoreWSFile } from '@services/ws'; import { makeSingleton } from '@singletons'; import { @@ -248,7 +248,7 @@ export class AddonModWorkshopPrefetchHandlerLazyService extends AddonModWorkshop }); }); - return CoreUtils.objectToArray(uniqueGrades); + return CoreObject.toArray(uniqueGrades); } /** diff --git a/src/addons/mod/workshop/services/workshop.ts b/src/addons/mod/workshop/services/workshop.ts index a6c7a4d3f..29f174567 100644 --- a/src/addons/mod/workshop/services/workshop.ts +++ b/src/addons/mod/workshop/services/workshop.ts @@ -20,7 +20,7 @@ import { CoreGradesMenuItem } from '@features/grades/services/grades-helper'; import { CoreNetwork } from '@services/network'; import { CoreSites, CoreSitesCommonWSOptions, CoreSitesReadingStrategy } from '@services/sites'; import { CoreTextFormat, defaultTextFormat } from '@singletons/text'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreArray } from '@singletons/array'; import { CoreStatusWithWarningsWSResponse, CoreWS, CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws'; import { makeSingleton, Translate } from '@singletons'; import { CoreFormFields } from '@singletons/form'; @@ -41,6 +41,7 @@ import { import { CoreSiteWSPreSets } from '@classes/sites/authenticated-site'; import { CoreCacheUpdateFrequency } from '@/core/constants'; import { CoreWSError } from '@classes/errors/wserror'; +import { CoreObject } from '@singletons/object'; declare module '@singletons/events' { @@ -366,7 +367,7 @@ export class AddonModWorkshopProvider { const response = await site.read('mod_workshop_get_user_plan', params, preSets); - return CoreUtils.arrayToObject(response.userplan.phases, 'code'); + return CoreArray.toObject(response.userplan.phases, 'code'); } /** @@ -1052,7 +1053,7 @@ export class AddonModWorkshopProvider { warnings: response.warnings, fields: this.parseFields(response.fields), current: this.parseFields(response.current), - options: CoreUtils.objectToKeyValueMap(response.options, 'name', 'value'), + options: CoreObject.toKeyValueMap(response.options, 'name', 'value'), }; } @@ -1183,7 +1184,7 @@ export class AddonModWorkshopProvider { const params: AddonModWorkshopUpdateAssessmentWSParams = { assessmentid: assessmentId, - data: CoreUtils.objectToArrayOfObjects(inputData, 'name', 'value'), + data: CoreObject.toArrayOfObjects(inputData, 'name', 'value'), }; const response = await site.write('mod_workshop_update_assessment', params); diff --git a/src/addons/notifications/services/notifications-helper.ts b/src/addons/notifications/services/notifications-helper.ts index 288f3bf69..c1661198d 100644 --- a/src/addons/notifications/services/notifications-helper.ts +++ b/src/addons/notifications/services/notifications-helper.ts @@ -14,7 +14,7 @@ import { Injectable } from '@angular/core'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreArray } from '@singletons/array'; import { makeSingleton } from '@singletons'; import { AddonMessageOutputDelegate } from '@addons/messageoutput/services/messageoutput-delegate'; import { @@ -53,7 +53,7 @@ export class AddonNotificationsHelperProvider { formattedPreferences.components.forEach((component) => { component.notifications.forEach((notification) => { - notification.processorsByName = CoreUtils.arrayToObject(notification.processors, 'name'); + notification.processorsByName = CoreArray.toObject(notification.processors, 'name'); }); }); diff --git a/src/addons/qtype/calculated/services/handlers/calculated.ts b/src/addons/qtype/calculated/services/handlers/calculated.ts index 86f100984..316372f10 100644 --- a/src/addons/qtype/calculated/services/handlers/calculated.ts +++ b/src/addons/qtype/calculated/services/handlers/calculated.ts @@ -17,7 +17,7 @@ import { Injectable, Type } from '@angular/core'; import { CoreQuestionQuestionParsed, CoreQuestionsAnswers } from '@features/question/services/question'; import { CoreQuestionHandler } from '@features/question/services/question-delegate'; import { convertTextToHTMLElement } from '@/core/utils/create-html-element'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreObject } from '@singletons/object'; import { makeSingleton } from '@singletons'; /** @@ -133,8 +133,8 @@ export class AddonQtypeCalculatedHandlerService implements CoreQuestionHandler { prevAnswers: CoreQuestionsAnswers, newAnswers: CoreQuestionsAnswers, ): boolean { - return CoreUtils.sameAtKeyMissingIsBlank(prevAnswers, newAnswers, 'answer') && - CoreUtils.sameAtKeyMissingIsBlank(prevAnswers, newAnswers, 'unit'); + return CoreObject.sameAtKeyMissingIsBlank(prevAnswers, newAnswers, 'answer') && + CoreObject.sameAtKeyMissingIsBlank(prevAnswers, newAnswers, 'unit'); } /** diff --git a/src/addons/qtype/essay/services/handlers/essay.ts b/src/addons/qtype/essay/services/handlers/essay.ts index 7884dfbab..1ded4f9db 100644 --- a/src/addons/qtype/essay/services/handlers/essay.ts +++ b/src/addons/qtype/essay/services/handlers/essay.ts @@ -24,7 +24,7 @@ import { CoreFileSession } from '@services/file-session'; import { CoreSites } from '@services/sites'; import { convertTextToHTMLElement } from '@/core/utils/create-html-element'; import { CoreText } from '@singletons/text'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreObject } from '@singletons/object'; import { CoreWSFile } from '@services/ws'; import { makeSingleton, Translate } from '@singletons'; import { CoreFileHelper } from '@services/file-helper'; @@ -267,7 +267,7 @@ export class AddonQtypeEssayHandlerService implements CoreQuestionHandler { // First check the inline text. const answerIsEqual = allowedOptions.text ? - CoreUtils.sameAtKeyMissingIsBlank(prevAnswers, newAnswers, 'answer') : true; + CoreObject.sameAtKeyMissingIsBlank(prevAnswers, newAnswers, 'answer') : true; if (!allowedOptions.attachments || !uploadFilesSupported || !answerIsEqual) { // No need to check attachments. diff --git a/src/addons/qtype/multichoice/services/handlers/multichoice.ts b/src/addons/qtype/multichoice/services/handlers/multichoice.ts index baf7526a9..9a02f2e2f 100644 --- a/src/addons/qtype/multichoice/services/handlers/multichoice.ts +++ b/src/addons/qtype/multichoice/services/handlers/multichoice.ts @@ -17,7 +17,7 @@ import { Injectable, Type } from '@angular/core'; import { AddonModQuizMultichoiceQuestion } from '@features/question/classes/base-question-component'; import { CoreQuestionQuestionParsed, CoreQuestionsAnswers } from '@features/question/services/question'; import { CoreQuestionHandler } from '@features/question/services/question-delegate'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreObject } from '@singletons/object'; import { makeSingleton } from '@singletons'; /** @@ -120,7 +120,7 @@ export class AddonQtypeMultichoiceHandlerService implements CoreQuestionHandler for (const name in newAnswers) { if (name.indexOf('choice') !== -1) { isSingle = false; - if (!CoreUtils.sameAtKeyMissingIsBlank(prevAnswers, newAnswers, name)) { + if (!CoreObject.sameAtKeyMissingIsBlank(prevAnswers, newAnswers, name)) { isMultiSame = false; break; } @@ -142,7 +142,7 @@ export class AddonQtypeMultichoiceHandlerService implements CoreQuestionHandler * @returns Whether they're the same. */ isSameResponseSingle(prevAnswers: CoreQuestionsAnswers, newAnswers: CoreQuestionsAnswers): boolean { - return CoreUtils.sameAtKeyMissingIsBlank(prevAnswers, newAnswers, 'answer'); + return CoreObject.sameAtKeyMissingIsBlank(prevAnswers, newAnswers, 'answer'); } /** diff --git a/src/addons/qtype/shortanswer/services/handlers/shortanswer.ts b/src/addons/qtype/shortanswer/services/handlers/shortanswer.ts index 37707448c..1f34de4de 100644 --- a/src/addons/qtype/shortanswer/services/handlers/shortanswer.ts +++ b/src/addons/qtype/shortanswer/services/handlers/shortanswer.ts @@ -16,7 +16,7 @@ import { Injectable, Type } from '@angular/core'; import { CoreQuestionQuestionParsed, CoreQuestionsAnswers } from '@features/question/services/question'; import { CoreQuestionHandler } from '@features/question/services/question-delegate'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreObject } from '@singletons/object'; import { makeSingleton } from '@singletons'; /** @@ -72,7 +72,7 @@ export class AddonQtypeShortAnswerHandlerService implements CoreQuestionHandler prevAnswers: CoreQuestionsAnswers, newAnswers: CoreQuestionsAnswers, ): boolean { - return CoreUtils.sameAtKeyMissingIsBlank(prevAnswers, newAnswers, 'answer'); + return CoreObject.sameAtKeyMissingIsBlank(prevAnswers, newAnswers, 'answer'); } } diff --git a/src/addons/qtype/truefalse/services/handlers/truefalse.ts b/src/addons/qtype/truefalse/services/handlers/truefalse.ts index f88d5a577..7e1b7bd03 100644 --- a/src/addons/qtype/truefalse/services/handlers/truefalse.ts +++ b/src/addons/qtype/truefalse/services/handlers/truefalse.ts @@ -16,7 +16,7 @@ import { Injectable, Type } from '@angular/core'; import { CoreQuestionHandler } from '@features/question/services/question-delegate'; import { CoreQuestionQuestionParsed, CoreQuestionsAnswers } from '@features/question/services/question'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreObject } from '@singletons/object'; import { AddonModQuizMultichoiceQuestion } from '@features/question/classes/base-question-component'; import { makeSingleton } from '@singletons'; @@ -74,7 +74,7 @@ export class AddonQtypeTrueFalseHandlerService implements CoreQuestionHandler { prevAnswers: CoreQuestionsAnswers, newAnswers: CoreQuestionsAnswers, ): boolean { - return CoreUtils.sameAtKeyMissingIsBlank(prevAnswers, newAnswers, 'answer'); + return CoreObject.sameAtKeyMissingIsBlank(prevAnswers, newAnswers, 'answer'); } /** diff --git a/src/core/classes/interceptor.ts b/src/core/classes/interceptor.ts index 0768dfeef..08b4d9ea5 100644 --- a/src/core/classes/interceptor.ts +++ b/src/core/classes/interceptor.ts @@ -66,7 +66,7 @@ export class CoreInterceptor implements HttpInterceptor { // Add the header and serialize the body if needed. const newReq = req.clone({ headers: req.headers.set('Content-Type', 'application/x-www-form-urlencoded'), - body: typeof req.body == 'object' && String(req.body) != '[object File]' ? + body: typeof req.body === 'object' && String(req.body) != '[object File]' ? CoreInterceptor.serialize(req.body) : req.body, }); diff --git a/src/core/classes/sites/authenticated-site.ts b/src/core/classes/sites/authenticated-site.ts index 6dd5c30fb..3ca4a21ae 100644 --- a/src/core/classes/sites/authenticated-site.ts +++ b/src/core/classes/sites/authenticated-site.ts @@ -43,6 +43,8 @@ import { CoreSiteWSCacheRecord } from '@services/database/sites'; import { CoreErrorLogs } from '@singletons/error-logs'; import { CoreWait } from '@singletons/wait'; import { CorePromiseUtils } from '@singletons/promise-utils'; +import { CoreObject } from '@singletons/object'; +import { CoreArray } from '@singletons/array'; /** * Class that represents a site (combination of site + user) where the user has authenticated but the site hasn't been validated @@ -212,7 +214,7 @@ export class CoreAuthenticatedSite extends CoreUnauthenticatedSite { // Index function by name to speed up wsAvailable method. if (infos?.functions) { - infos.functionsByName = CoreUtils.arrayToObject(infos.functions, 'name'); + infos.functionsByName = CoreArray.toObject(infos.functions, 'name'); } } @@ -1020,7 +1022,7 @@ export class CoreAuthenticatedSite extends CoreUnauthenticatedSite { */ // eslint-disable-next-line @typescript-eslint/no-explicit-any protected getCacheId(method: string, data: any): string { - return Md5.hashAsciiStr(method + ':' + CoreUtils.sortAndStringify(data)); + return Md5.hashAsciiStr(method + ':' + CoreObject.sortAndStringify(data)); } /** diff --git a/src/core/features/block/classes/base-block-component.ts b/src/core/features/block/classes/base-block-component.ts index 86f74c90b..1d6aa2f35 100644 --- a/src/core/features/block/classes/base-block-component.ts +++ b/src/core/features/block/classes/base-block-component.ts @@ -15,7 +15,7 @@ import { OnInit, Input, Component, Optional, Inject, OnChanges, SimpleChanges } from '@angular/core'; import { CoreLogger } from '@singletons/logger'; import { CoreDomUtils } from '@services/utils/dom'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreArray } from '@singletons/array'; import { CoreText } from '@singletons/text'; import { CoreCourseBlock } from '../../course/services/course'; import { Params } from '@angular/router'; @@ -78,7 +78,7 @@ export abstract class CoreBlockBaseComponent implements OnInit, OnChanges, ICore config.value = CoreText.parseJSON(config.value); }); - this.block.configsRecord = CoreUtils.arrayToObject(this.block.configs, 'name'); + this.block.configsRecord = CoreArray.toObject(this.block.configs, 'name'); } /** diff --git a/src/core/features/course/pages/contents/contents.ts b/src/core/features/course/pages/contents/contents.ts index 0ec34c8de..5df61bb9e 100644 --- a/src/core/features/course/pages/contents/contents.ts +++ b/src/core/features/course/pages/contents/contents.ts @@ -47,6 +47,7 @@ import { CORE_COURSE_PROGRESS_UPDATED_EVENT, } from '@features/course/constants'; import { CorePromiseUtils } from '@singletons/promise-utils'; +import { CoreObject } from '@singletons/object'; /** * Page that displays the contents of a course. @@ -284,7 +285,7 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy, CoreRefreshCon if ('courseformatoptions' in this.course && this.course.courseformatoptions) { // Already loaded. - this.formatOptions = CoreUtils.objectToKeyValueMap(this.course.courseformatoptions, 'name', 'value'); + this.formatOptions = CoreObject.toKeyValueMap(this.course.courseformatoptions, 'name', 'value'); return; } @@ -294,7 +295,7 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy, CoreRefreshCon course && Object.assign(this.course, course); if (course?.courseformatoptions) { - this.formatOptions = CoreUtils.objectToKeyValueMap(course.courseformatoptions, 'name', 'value'); + this.formatOptions = CoreObject.toKeyValueMap(course.courseformatoptions, 'name', 'value'); } } diff --git a/src/core/features/course/services/course-helper.ts b/src/core/features/course/services/course-helper.ts index e4c7f7c4d..16f50b174 100644 --- a/src/core/features/course/services/course-helper.ts +++ b/src/core/features/course/services/course-helper.ts @@ -32,7 +32,7 @@ import { CoreLogger } from '@singletons/logger'; import { ApplicationInit, makeSingleton, Translate } from '@singletons'; import { CoreFilepool } from '@services/filepool'; import { CoreDomUtils } from '@services/utils/dom'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreArray } from '@singletons/array'; import { CoreCourseAnyCourseData, CoreCourseBasicData, @@ -1088,7 +1088,7 @@ export class CoreCourseHelperProvider { const totalOffline = offlineCompletions.length; let loaded = 0; - const offlineCompletionsMap = CoreUtils.arrayToObject(offlineCompletions, 'cmid'); + const offlineCompletionsMap = CoreArray.toObject(offlineCompletions, 'cmid'); const loadSectionOfflineCompletion = (section: CoreCourseWSSection): void => { if (!section.contents || !section.contents.length) { diff --git a/src/core/features/course/services/course.ts b/src/core/features/course/services/course.ts index 6281e2009..3db9b068f 100644 --- a/src/core/features/course/services/course.ts +++ b/src/core/features/course/services/course.ts @@ -20,7 +20,6 @@ import { CoreEvents } from '@singletons/events'; import { CoreLogger } from '@singletons/logger'; import { CoreSitesCommonWSOptions, CoreSites, CoreSitesReadingStrategy } from '@services/sites'; import { CoreTimeUtils } from '@services/utils/time'; -import { CoreUtils } from '@services/utils/utils'; import { CoreSite } from '@classes/sites/site'; import { CoreCacheUpdateFrequency, CoreConstants, DownloadStatus } from '@/core/constants'; import { makeSingleton, Translate } from '@singletons'; @@ -75,6 +74,7 @@ import { CORE_COURSE_STEALTH_MODULES_SECTION_ID, } from '../constants'; import { CorePromiseUtils } from '@singletons/promise-utils'; +import { CoreObject } from '@singletons/object'; export type CoreCourseProgressUpdated = { progress: number; courseId: number }; @@ -260,7 +260,7 @@ export class CoreCourseProvider { } const course = await CoreCourses.getCourseByField('id', courseId, site.id); - const formatOptions = CoreUtils.objectToKeyValueMap( + const formatOptions = CoreObject.toKeyValueMap( course.courseformatoptions ?? [], 'name', 'value', @@ -353,7 +353,7 @@ export class CoreCourseProvider { throw Error('WS core_completion_get_activities_completion_status failed'); } - const completionStatus = CoreUtils.arrayToObject(data.statuses, 'cmid'); + const completionStatus = CoreArray.toObject(data.statuses, 'cmid'); if (!includeOffline) { return completionStatus; } @@ -412,7 +412,7 @@ export class CoreCourseProvider { js: (record) => ids.includes(record.cmId), }); - return CoreUtils.arrayToObject(entries, 'cmId'); + return CoreArray.toObject(entries, 'cmId'); } /** diff --git a/src/core/features/course/services/log-helper.ts b/src/core/features/course/services/log-helper.ts index 10a62bde6..7fa1520ed 100644 --- a/src/core/features/course/services/log-helper.ts +++ b/src/core/features/course/services/log-helper.ts @@ -18,7 +18,7 @@ import { CoreNetwork } from '@services/network'; import { CoreSites } from '@services/sites'; import { CoreText } from '@singletons/text'; import { CoreTimeUtils } from '@services/utils/time'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreObject } from '@singletons/object'; import { makeSingleton } from '@singletons'; import { ACTIVITY_LOG_TABLE, CoreCourseActivityLogDBRecord } from './database/log'; import { CoreStatusWithWarningsWSResponse } from '@services/ws'; @@ -84,7 +84,7 @@ export class CoreCourseLogHelperProvider { const conditions: Partial = { ws, - data: CoreUtils.sortAndStringify(data), + data: CoreObject.sortAndStringify(data), }; await site.getDb().deleteRecords(ACTIVITY_LOG_TABLE, conditions); @@ -264,7 +264,7 @@ export class CoreCourseLogHelperProvider { component, componentid: componentId, ws, - data: CoreUtils.sortAndStringify(data), + data: CoreObject.sortAndStringify(data), time: CoreTimeUtils.timestamp(), }; diff --git a/src/core/features/course/services/module-prefetch-delegate.ts b/src/core/features/course/services/module-prefetch-delegate.ts index 4c8a63204..0a28bd98c 100644 --- a/src/core/features/course/services/module-prefetch-delegate.ts +++ b/src/core/features/course/services/module-prefetch-delegate.ts @@ -21,7 +21,7 @@ import { CoreFileHelper } from '@services/file-helper'; import { CoreFilepool } from '@services/filepool'; import { CoreSites } from '@services/sites'; import { CoreTimeUtils } from '@services/utils/time'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreArray } from '@singletons/array'; import { CoreCourse, CoreCourseAnyModuleData, CoreCourseModuleContentFile } from './course'; import { CoreCache } from '@classes/cache'; import { CoreSiteWSPreSets } from '@classes/sites/authenticated-site'; @@ -1317,7 +1317,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate(response.instances, 'id', result); + CoreArray.toObject(response.instances, 'id', result); // Treat warnings, adding the not supported modules. response.warnings?.forEach((warning) => { diff --git a/src/core/features/courses/services/courses-helper.ts b/src/core/features/courses/services/courses-helper.ts index 386ce9590..742babb1b 100644 --- a/src/core/features/courses/services/courses-helper.ts +++ b/src/core/features/courses/services/courses-helper.ts @@ -13,7 +13,7 @@ // limitations under the License. import { Injectable } from '@angular/core'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreArray } from '@singletons/array'; import { CoreSites, CoreSitesCommonWSOptions } from '@services/sites'; import { CoreCourseAnyCourseData, @@ -157,7 +157,7 @@ export class CoreCoursesHelperProvider { // Get the extra data for the courses. return CoreCourses.getCoursesByFieldObservable('ids', courseIds, options).pipe(map(coursesInfosArray => { - const coursesInfo = CoreUtils.arrayToObject(coursesInfosArray, 'id'); + const coursesInfo = CoreArray.toObject(coursesInfosArray, 'id'); courses.forEach((course) => { this.loadCourseExtraInfo(course, coursesInfo[course.id], loadCategoryNames); diff --git a/src/core/features/editor/services/editor-offline.ts b/src/core/features/editor/services/editor-offline.ts index b6a7e912f..b8f84836a 100644 --- a/src/core/features/editor/services/editor-offline.ts +++ b/src/core/features/editor/services/editor-offline.ts @@ -16,7 +16,7 @@ import { Injectable } from '@angular/core'; import { CoreError } from '@classes/errors/error'; import { CoreSites } from '@services/sites'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreObject } from '@singletons/object'; import { makeSingleton } from '@singletons'; import { CoreLogger } from '@singletons/logger'; import { CoreEditorDraft, CoreEditorDraftPrimaryData, DRAFT_TABLE } from './database/editor'; @@ -82,7 +82,7 @@ export class CoreEditorOfflineProvider { contextlevel: contextLevel, contextinstanceid: contextInstanceId, elementid: elementId, - extraparams: CoreUtils.sortAndStringify(extraParams || {}), + extraparams: CoreObject.sortAndStringify(extraParams || {}), }; } diff --git a/src/core/features/fileuploader/services/fileuploader-helper.ts b/src/core/features/fileuploader/services/fileuploader-helper.ts index a51b8a29c..745b37bd7 100644 --- a/src/core/features/fileuploader/services/fileuploader-helper.ts +++ b/src/core/features/fileuploader/services/fileuploader-helper.ts @@ -24,7 +24,7 @@ import { CoreFile, CoreFileProvider, CoreFileProgressEvent } from '@services/fil import { CoreDomUtils } from '@services/utils/dom'; import { CoreMimetypeUtils } from '@services/utils/mimetype'; import { CoreText } from '@singletons/text'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreArray } from '@singletons/array'; import { makeSingleton, Translate, Camera, ActionSheetController } from '@singletons'; import { CoreLogger } from '@singletons/logger'; import { CoreCanceledError } from '@classes/errors/cancelederror'; @@ -635,8 +635,8 @@ export class CoreFileUploaderHelperProvider { }; if (fromAlbum) { - const imageSupported = !mimetypes || CoreUtils.indexOfRegexp(mimetypes, /^image\//) > -1; - const videoSupported = !mimetypes || CoreUtils.indexOfRegexp(mimetypes, /^video\//) > -1; + const imageSupported = !mimetypes || CoreArray.indexOfRegexp(mimetypes, /^image\//) > -1; + const videoSupported = !mimetypes || CoreArray.indexOfRegexp(mimetypes, /^video\//) > -1; options.sourceType = Camera.PictureSourceType.PHOTOLIBRARY; options.popoverOptions = { diff --git a/src/core/features/grades/services/grades-helper.ts b/src/core/features/grades/services/grades-helper.ts index c4884b74e..6a0afaaf2 100644 --- a/src/core/features/grades/services/grades-helper.ts +++ b/src/core/features/grades/services/grades-helper.ts @@ -47,6 +47,7 @@ import { CoreLoadings } from '@services/loadings'; import { convertTextToHTMLElement } from '@/core/utils/create-html-element'; import { CoreCourseAccessDataType } from '@features/course/constants'; import { CorePromiseUtils } from '@singletons/promise-utils'; +import { CoreArray } from '@singletons/array'; export const GRADES_PAGE_NAME = 'grades'; export const GRADES_PARTICIPANTS_PAGE_NAME = 'participant-grades'; @@ -271,7 +272,7 @@ export class CoreGradesHelperProvider { try { const courses = await CoreCourses.getUserCourses(undefined, undefined, CoreSitesReadingStrategy.ONLY_CACHE); - const coursesMap = CoreUtils.arrayToObject(courses, 'id'); + const coursesMap = CoreArray.toObject(courses, 'id'); coursesWereMissing = this.addCourseData(grades, coursesMap); } catch { @@ -282,7 +283,7 @@ export class CoreGradesHelperProvider { if (coursesWereMissing) { const courses = await CoreCourses.getCoursesByField('ids', grades.map((grade) => grade.courseid).join(',')); const coursesMap = - CoreUtils.arrayToObject(courses as Record[], 'id') as + CoreArray.toObject(courses as Record[], 'id') as Record | Record; diff --git a/src/core/features/h5p/classes/content-validator.ts b/src/core/features/h5p/classes/content-validator.ts index 25fa5bb6b..a98734cfb 100644 --- a/src/core/features/h5p/classes/content-validator.ts +++ b/src/core/features/h5p/classes/content-validator.ts @@ -18,6 +18,7 @@ import { CoreH5P } from '@features/h5p/services/h5p'; import { Translate } from '@singletons'; import { CoreH5PCore, CoreH5PLibraryData, CoreH5PLibraryAddonData, CoreH5PContentDepsTreeDependency } from './core'; import { CoreArray } from '@singletons/array'; +import { CoreObject } from '@singletons/object'; const ALLOWED_STYLEABLE_TAGS = ['span', 'p', 'div', 'h1', 'h2', 'h3', 'table', 'col', 'figure', 'td', 'th', 'li']; @@ -354,7 +355,7 @@ export class CoreH5PContentValidator { } if (!isArray) { - list = CoreUtils.objectToArray(> list); + list = CoreObject.toArray(> list); } if (!list.length) { @@ -677,7 +678,7 @@ export class CoreH5PContentValidator { */ protected filterXssSplit(tags: string[], store: boolean = false): string { if (store) { - this.allowedHtml = CoreUtils.arrayToObject(tags); + this.allowedHtml = CoreArray.toObject(tags); return ''; } diff --git a/src/core/features/h5p/classes/core.ts b/src/core/features/h5p/classes/core.ts index 59396bbef..d186c14d7 100644 --- a/src/core/features/h5p/classes/core.ts +++ b/src/core/features/h5p/classes/core.ts @@ -961,7 +961,7 @@ export class CoreH5PCore { if (params.match(pattern)) { return true; } - } else if (typeof params == 'object') { + } else if (typeof params === 'object') { for (const key in params) { const value = params[key]; diff --git a/src/core/features/login/services/login-helper.ts b/src/core/features/login/services/login-helper.ts index f877011c4..367d19c48 100644 --- a/src/core/features/login/services/login-helper.ts +++ b/src/core/features/login/services/login-helper.ts @@ -23,7 +23,7 @@ import { CoreSites, CoreLoginSiteInfo, CoreSiteBasicInfo } from '@services/sites import { CoreWS, CoreWSExternalWarning } from '@services/ws'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreText } from '@singletons/text'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreObject } from '@singletons/object'; import { CoreConstants } from '@/core/constants'; import { CoreSite } from '@classes/sites/site'; import { CoreError } from '@classes/errors/error'; @@ -1368,7 +1368,7 @@ export class CoreLoginHelperProvider { return; })); - accountsList.otherSites = CoreUtils.objectToArray(otherSites); + accountsList.otherSites = CoreObject.toArray(otherSites); return accountsList; } diff --git a/src/core/features/mainmenu/pages/home/home.ts b/src/core/features/mainmenu/pages/home/home.ts index ab928b4c7..31dacfced 100644 --- a/src/core/features/mainmenu/pages/home/home.ts +++ b/src/core/features/mainmenu/pages/home/home.ts @@ -19,7 +19,7 @@ import { CoreSites } from '@services/sites'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreTabsOutletComponent, CoreTabsOutletTab } from '@components/tabs-outlet/tabs-outlet'; import { CoreMainMenuHomeDelegate, CoreMainMenuHomeHandlerToDisplay } from '../../services/home-delegate'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreArray } from '@singletons/array'; import { CoreMainMenuHomeHandlerService } from '@features/mainmenu/services/handlers/mainmenu'; /** @@ -62,7 +62,7 @@ export class CoreMainMenuHomePage implements OnInit { initHandlers(handlers: CoreMainMenuHomeHandlerToDisplay[]): void { // Re-build the list of tabs. const loaded = CoreMainMenuHomeDelegate.areHandlersLoaded(); - const handlersMap = CoreUtils.arrayToObject(handlers, 'title'); + const handlersMap = CoreArray.toObject(handlers, 'title'); const newTabs = handlers.map((handler): CoreTabsOutletTab => { const tab = this.tabs.find(tab => tab.title == handler.title); diff --git a/src/core/features/question/services/question.ts b/src/core/features/question/services/question.ts index 1426bba3d..99331ff7b 100644 --- a/src/core/features/question/services/question.ts +++ b/src/core/features/question/services/question.ts @@ -18,7 +18,7 @@ import { CoreFile } from '@services/file'; import { CoreSites } from '@services/sites'; import { CoreText } from '@singletons/text'; import { CoreTimeUtils } from '@services/utils/time'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreArray } from '@singletons/array'; import { CoreWSExternalFile } from '@services/ws'; import { makeSingleton } from '@singletons'; import { CorePath } from '@singletons/path'; @@ -37,6 +37,7 @@ import { QUESTION_NEEDS_GRADING_STATE_CLASSES, QUESTION_TODO_STATE_CLASSES, } from '@features/question/constants'; +import { CoreObject } from '@singletons/object'; const QUESTION_PREFIX_REGEX = /q\d+:(\d+)_/; const STATES: Record = { @@ -150,7 +151,7 @@ export class CoreQuestionProvider { */ compareAllAnswers(prevAnswers: Record, newAnswers: Record): boolean { // Get all the keys. - const keys = CoreUtils.mergeArraysWithoutDuplicates(Object.keys(prevAnswers), Object.keys(newAnswers)); + const keys = CoreArray.mergeWithoutDuplicates(Object.keys(prevAnswers), Object.keys(newAnswers)); // Check that all the keys have the same value on both objects. for (const i in keys) { @@ -158,7 +159,7 @@ export class CoreQuestionProvider { // Ignore extra answers like sequencecheck or certainty. if (!this.isExtraAnswer(key[0])) { - if (!CoreUtils.sameAtKeyMissingIsBlank(prevAnswers, newAnswers, key)) { + if (!CoreObject.sameAtKeyMissingIsBlank(prevAnswers, newAnswers, key)) { return false; } } diff --git a/src/core/features/rating/services/rating.ts b/src/core/features/rating/services/rating.ts index 9187a49a1..ad3f21220 100644 --- a/src/core/features/rating/services/rating.ts +++ b/src/core/features/rating/services/rating.ts @@ -18,13 +18,13 @@ import { CoreSite } from '@classes/sites/site'; import { CoreUser } from '@features/user/services/user'; import { CoreNetwork } from '@services/network'; import { CoreSites } from '@services/sites'; -import { CoreUtils } from '@services/utils/utils'; import { CoreWSExternalWarning } from '@services/ws'; import { makeSingleton } from '@singletons'; import { CoreEvents } from '@singletons/events'; import { CoreRatingOffline } from './rating-offline'; import { CoreSiteWSPreSets } from '@classes/sites/authenticated-site'; import { CoreWSError } from '@classes/errors/wserror'; +import { CoreObject } from '@singletons/object'; const ROOT_CACHE_KEY = 'CoreRating:'; @@ -351,8 +351,8 @@ export class CoreRatingProvider { }); if (result) { - result.scales = CoreUtils.objectToArray(scales); - result.ratings = CoreUtils.objectToArray(ratings); + result.scales = CoreObject.toArray(scales); + result.ratings = CoreObject.toArray(ratings); } return result; diff --git a/src/core/features/settings/pages/space-usage/space-usage.ts b/src/core/features/settings/pages/space-usage/space-usage.ts index 3b410690d..f83368dec 100644 --- a/src/core/features/settings/pages/space-usage/space-usage.ts +++ b/src/core/features/settings/pages/space-usage/space-usage.ts @@ -15,7 +15,7 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; import { CoreSiteBasicInfo, CoreSites } from '@services/sites'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreObject } from '@singletons/object'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreSettingsHelper } from '../../services/settings-helper'; @@ -129,7 +129,7 @@ export class CoreSettingsSpaceUsagePage implements OnInit, OnDestroy { } }); - this.accountsList.otherSites = CoreUtils.objectToArray(otherSites); + this.accountsList.otherSites = CoreObject.toArray(otherSites); this.accountsList.count = sites.length; this.totalSpaceUsage = totalSize; diff --git a/src/core/features/siteplugins/classes/compile-init-component.ts b/src/core/features/siteplugins/classes/compile-init-component.ts index 6fe45e777..8949f015c 100644 --- a/src/core/features/siteplugins/classes/compile-init-component.ts +++ b/src/core/features/siteplugins/classes/compile-init-component.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { CoreUtils } from '@services/utils/utils'; +import { CoreObject } from '@singletons/object'; import { CoreSitePlugins, CoreSitePluginsInitHandlerData } from '../services/siteplugins'; /** @@ -55,7 +55,7 @@ export class CoreSitePluginsCompileInitComponent { // Load first template. if (this.handlerSchema.methodTemplates?.length) { this.content = this.handlerSchema.methodTemplates[0].html; - this.jsData.CONTENT_TEMPLATES = CoreUtils.objectToKeyValueMap( + this.jsData.CONTENT_TEMPLATES = CoreObject.toKeyValueMap( this.handlerSchema.methodTemplates, 'id', 'html', diff --git a/src/core/features/siteplugins/services/siteplugins.ts b/src/core/features/siteplugins/services/siteplugins.ts index 8f9927e2a..63b1d3e30 100644 --- a/src/core/features/siteplugins/services/siteplugins.ts +++ b/src/core/features/siteplugins/services/siteplugins.ts @@ -34,6 +34,7 @@ import { CoreEnrolAction, CoreEnrolInfoIcon } from '@features/enrol/services/enr import { CoreSiteWSPreSets } from '@classes/sites/authenticated-site'; import { CoreUserProfileHandlerType } from '@features/user/services/user-delegate'; import { CORE_SITE_PLUGINS_COMPONENT, CORE_SITE_PLUGINS_UPDATE_COURSE_CONTENT } from '../constants'; +import { CoreObject } from '@singletons/object'; /** * Service to provide functionalities regarding site plugins. @@ -156,13 +157,13 @@ export class CoreSitePluginsProvider { data = Object.assign(data, initResult.jsResult || {}); // Now add some data returned by the init WS call. - data.INIT_TEMPLATES = CoreUtils.objectToKeyValueMap(initResult.templates, 'id', 'html'); + data.INIT_TEMPLATES = CoreObject.toKeyValueMap(initResult.templates, 'id', 'html'); data.INIT_OTHERDATA = initResult.otherdata; } if (contentResult) { // Now add the data returned by the content WS call. - data.CONTENT_TEMPLATES = CoreUtils.objectToKeyValueMap(contentResult.templates, 'id', 'html'); + data.CONTENT_TEMPLATES = CoreObject.toKeyValueMap(contentResult.templates, 'id', 'html'); data.CONTENT_OTHERDATA = contentResult.otherdata; } @@ -177,7 +178,7 @@ export class CoreSitePluginsProvider { * @returns Cache key. */ getCallWSCacheKey(method: string, data: Record): string { - return this.getCallWSCommonCacheKey(method) + ':' + CoreUtils.sortAndStringify(data); + return this.getCallWSCommonCacheKey(method) + ':' + CoreObject.sortAndStringify(data); } /** @@ -219,7 +220,7 @@ export class CoreSitePluginsProvider { const data: CoreSitePluginsGetContentWSParams = { component: component, method: method, - args: CoreUtils.objectToArrayOfObjects(argsToSend, 'name', 'value', true), + args: CoreObject.toArrayOfObjects(argsToSend, 'name', 'value', true), }; preSets = preSets || {}; @@ -230,7 +231,7 @@ export class CoreSitePluginsProvider { let otherData: Record = {}; if (result.otherdata) { - otherData = > CoreUtils.objectToKeyValueMap(result.otherdata, 'name', 'value'); + otherData = > CoreObject.toKeyValueMap(result.otherdata, 'name', 'value'); // Try to parse all properties that could be JSON encoded strings. for (const name in otherData) { @@ -255,7 +256,7 @@ export class CoreSitePluginsProvider { */ protected getContentCacheKey(component: string, method: string, args: Record): string { return CoreSitePluginsProvider.ROOT_CACHE_KEY + 'content:' + component + ':' + method + - ':' + CoreUtils.sortAndStringify(args); + ':' + CoreObject.sortAndStringify(args); } /** @@ -346,7 +347,7 @@ export class CoreSitePluginsProvider { * @returns Plugin list ws info. */ getCurrentSitePluginList(): CoreSitePluginsWSPlugin[] { - return CoreUtils.objectToArray(this.sitePlugins).map((plugin) => plugin.plugin); + return CoreObject.toArray(this.sitePlugins).map((plugin) => plugin.plugin); } /** @@ -507,7 +508,7 @@ export class CoreSitePluginsProvider { for (const i in useOtherData) { const name = useOtherData[i]; - if (typeof otherData[name] == 'object' && otherData[name] !== null) { + if (typeof otherData[name] === 'object' && otherData[name] !== null) { // Stringify objects. args[name] = JSON.stringify(otherData[name]); } else { @@ -517,7 +518,7 @@ export class CoreSitePluginsProvider { } else { // Add all the data to args. for (const name in otherData) { - if (typeof otherData[name] == 'object' && otherData[name] !== null) { + if (typeof otherData[name] === 'object' && otherData[name] !== null) { // Stringify objects. args[name] = JSON.stringify(otherData[name]); } else { diff --git a/src/core/services/filepool.ts b/src/core/services/filepool.ts index a415a5868..5151214d2 100644 --- a/src/core/services/filepool.ts +++ b/src/core/services/filepool.ts @@ -27,7 +27,7 @@ import { CoreMimetypeUtils } from '@services/utils/mimetype'; import { CoreText } from '@singletons/text'; import { CoreTimeUtils } from '@services/utils/time'; import { CoreUrl, CoreUrlPartNames } from '@singletons/url'; -import { CoreUtils } from '@services/utils/utils'; +import { CoreArray } from '@singletons/array'; import { CoreError } from '@classes/errors/error'; import { DownloadStatus } from '@/core/constants'; import { ApplicationInit, makeSingleton, NgZone, Translate } from '@singletons'; @@ -650,7 +650,7 @@ export class CoreFilepoolProvider { ]); // Notify now. - const filesLinksMap = CoreUtils.arrayToObjectMultiple(filesLinks, 'fileId'); + const filesLinksMap = CoreArray.toObjectMultiple(filesLinks, 'fileId'); filesEntries.forEach(entry => this.notifyFileDeleted(siteId, entry.fileId, filesLinksMap[entry.fileId] || [])); } diff --git a/src/core/services/geolocation.ts b/src/core/services/geolocation.ts index 5d861be5c..e14b37acb 100644 --- a/src/core/services/geolocation.ts +++ b/src/core/services/geolocation.ts @@ -154,7 +154,7 @@ export class CoreGeolocationProvider { */ protected isCordovaPermissionDeniedError(error?: CoreAnyError | GeolocationPositionError): boolean { return !!error && - typeof error == 'object' && + typeof error === 'object' && 'code' in error && 'PERMISSION_DENIED' in error && error.code === error.PERMISSION_DENIED; diff --git a/src/core/services/local-notifications.ts b/src/core/services/local-notifications.ts index 577de8730..f566855a8 100644 --- a/src/core/services/local-notifications.ts +++ b/src/core/services/local-notifications.ts @@ -290,7 +290,7 @@ export class CoreLocalNotificationsProvider { scheduled.forEach((notif) => { notif.data = this.parseNotificationData(notif.data); - if (notif.id && typeof notif.data == 'object' && notif.data.siteId === siteId) { + if (notif.id && typeof notif.data === 'object' && notif.data.siteId === siteId) { ids.push(notif.id); } }); @@ -563,7 +563,7 @@ export class CoreLocalNotificationsProvider { try { // Check if request is valid. - if (typeof request != 'object' || request.table === undefined || request.id === undefined) { + if (typeof request !== 'object' || request.table === undefined || request.id === undefined) { return; } diff --git a/src/core/services/navigator.ts b/src/core/services/navigator.ts index f953b1785..e86ae2ec1 100644 --- a/src/core/services/navigator.ts +++ b/src/core/services/navigator.ts @@ -461,7 +461,7 @@ export class CoreNavigatorService { return route; } - if (routeData && CoreUtils.basicLeftCompare(routeData, this.getRouteData(route), 3)) { + if (routeData && CoreObject.basicLeftCompare(routeData, this.getRouteData(route), 3)) { return route; } @@ -607,7 +607,7 @@ export class CoreNavigatorService { protected replaceObjectParams(queryParams?: Params | null): void { for (const name in queryParams) { const value = queryParams[name]; - if (typeof value != 'object' || value === null) { + if (typeof value !== 'object' || value === null) { continue; } diff --git a/src/core/services/sites.ts b/src/core/services/sites.ts index 168574f0c..be8ef72f1 100644 --- a/src/core/services/sites.ts +++ b/src/core/services/sites.ts @@ -1292,7 +1292,7 @@ export class CoreSitesProvider { return !!this.currentSite; } - const siteId = typeof site == 'object' ? site.getId() : site; + const siteId = typeof site === 'object' ? site.getId() : site; return this.currentSite.getId() === siteId; } diff --git a/src/core/services/utils/dom.ts b/src/core/services/utils/dom.ts index d2f11a7fd..2881e40c6 100644 --- a/src/core/services/utils/dom.ts +++ b/src/core/services/utils/dom.ts @@ -447,7 +447,7 @@ export class CoreDomUtilsProvider { let extraInfo = ''; let errorMessage: string | undefined; - if (typeof error == 'object') { + if (typeof error === 'object') { if (this.debugDisplay) { // Get the debug info. Escape the HTML so it is displayed as it is in the view. if ('debuginfo' in error && error.debuginfo) { diff --git a/src/core/services/utils/iframe.ts b/src/core/services/utils/iframe.ts index a6f2ead98..710568119 100644 --- a/src/core/services/utils/iframe.ts +++ b/src/core/services/utils/iframe.ts @@ -455,7 +455,7 @@ export class CoreIframeUtilsProvider { return; } - if (element.tagName.toLowerCase() == 'object') { + if (element.tagName.toLowerCase() === 'object') { element.setAttribute('data', url); } else { element.setAttribute('src', url); @@ -509,7 +509,7 @@ export class CoreIframeUtilsProvider { (!link.target || link.target == '_self') ) { // Load the link inside the frame itself. - if (element.tagName.toLowerCase() == 'object') { + if (element.tagName.toLowerCase() === 'object') { element.setAttribute('data', link.href); } else { element.setAttribute('src', link.href); @@ -546,7 +546,7 @@ export class CoreIframeUtilsProvider { } else if (CorePlatform.isIOS() && (!link.target || link.target == '_self') && element) { // In cordova ios 4.1.0 links inside iframes stopped working. We'll manually treat them. event && event.preventDefault(); - if (element.tagName.toLowerCase() == 'object') { + if (element.tagName.toLowerCase() === 'object') { element.setAttribute('data', link.href); } else { element.setAttribute('src', link.href); diff --git a/src/core/services/utils/mimetype.ts b/src/core/services/utils/mimetype.ts index 448734af5..a2f63d1f3 100644 --- a/src/core/services/utils/mimetype.ts +++ b/src/core/services/utils/mimetype.ts @@ -424,10 +424,10 @@ export class CoreMimetypeUtilsProvider { let mimetype: string | undefined = ''; let extension: string | undefined = ''; - if (typeof obj == 'object' && CoreFileUtils.isFileEntry(obj)) { + if (typeof obj === 'object' && CoreFileUtils.isFileEntry(obj)) { // It's a FileEntry. Don't use the file function because it's asynchronous and the type isn't reliable. filename = obj.name; - } else if (typeof obj == 'object') { + } else if (typeof obj === 'object') { filename = obj.filename || ''; mimetype = obj.mimetype || ''; } else { diff --git a/src/core/services/utils/utils.ts b/src/core/services/utils/utils.ts index fd54593e3..8fe25b9a2 100644 --- a/src/core/services/utils/utils.ts +++ b/src/core/services/utils/utils.ts @@ -30,6 +30,7 @@ import { CoreErrorHelper } from '@services/error-helper'; import { CorePromiseUtils, OrderedPromiseData } from '@singletons/promise-utils'; import { CoreOpener, CoreOpenerOpenFileOptions, CoreOpenerOpenInBrowserOptions } from '@singletons/opener'; import { CoreCountries, CoreCountry } from '@singletons/countries'; +import { CoreObject } from '@singletons/object'; export type TreeNode = T & { children: TreeNode[] }; @@ -89,19 +90,14 @@ export class CoreUtilsProvider { * @param propertyName The name of the property to use as the key. If not provided, the whole item will be used. * @param result Object where to put the properties. If not defined, a new object will be created. * @returns The object. + * @deprecated since 5.0. Use CoreArray.toObject instead. */ arrayToObject( array: T[] = [], propertyName?: string, result: Record = {}, ): Record { - for (const entry of array) { - const key = propertyName ? entry[propertyName] : entry; - - result[key] = entry; - } - - return result; + return CoreArray.toObject(array, propertyName, result); } /** @@ -124,22 +120,14 @@ export class CoreUtilsProvider { * @param propertyName The name of the property to use as the key. If not provided, the whole item will be used. * @param result Object where to put the properties. If not defined, a new object will be created. * @returns The object. + * @deprecated since 5.0. Use CoreArray.toObjectMultiple instead. */ arrayToObjectMultiple( array: T[] = [], propertyName?: string, result: Record = {}, ): Record { - for (const entry of array) { - const key = propertyName ? entry[propertyName] : entry; - if (result[key] === undefined) { - result[key] = []; - } - - result[key].push(entry); - } - - return result; + return CoreArray.toObjectMultiple(array, propertyName, result); } /** @@ -153,6 +141,7 @@ export class CoreUtilsProvider { * @param level Current deep level (when comparing objects). * @param undefinedIsNull True if undefined is equal to null. Defaults to true. * @returns Whether both items are equal. + * @deprecated since 5.0. Use CoreObject.basicLeftCompare instead. */ basicLeftCompare( itemA: any, // eslint-disable-line @typescript-eslint/no-explicit-any @@ -161,43 +150,7 @@ export class CoreUtilsProvider { level: number = 0, undefinedIsNull: boolean = true, ): boolean { - if (typeof itemA == 'function' || typeof itemB == 'function') { - return true; // Don't compare functions. - } else if (typeof itemA == 'object' && typeof itemB == 'object') { - if (level >= maxLevels) { - return true; // Max deep reached. - } - - let equal = true; - for (const name in itemA) { - const value = itemA[name]; - if (name == '$$hashKey') { - // Ignore $$hashKey property since it's a "calculated" property. - continue; - } - - if (!this.basicLeftCompare(value, itemB[name], maxLevels, level + 1)) { - equal = false; - } - } - - return equal; - } else { - if (undefinedIsNull && ( - (itemA === undefined && itemB === null) || (itemA === null && itemB === undefined))) { - return true; - } - - // We'll treat "2" and 2 as the same value. - const floatA = parseFloat(itemA); - const floatB = parseFloat(itemB); - - if (!isNaN(floatA) && !isNaN(floatB)) { - return floatA == floatB; - } - - return itemA === itemB; - } + return CoreObject.basicLeftCompare(itemA, itemB, maxLevels, level, undefinedIsNull); } /** @@ -291,7 +244,7 @@ export class CoreUtilsProvider { } return newArray; - } else if (this.isObject(source)) { + } else if (CoreObject.isObject(source)) { // Check if the object shouldn't be copied. if (source.toString && this.DONT_CLONE.indexOf(source.toString()) != -1) { // Object shouldn't be copied, return it as it is. @@ -383,32 +336,10 @@ export class CoreUtilsProvider { * @param obj Object to flatten. * @param useDotNotation Whether to use dot notation '.' or square brackets '['. * @returns Flattened object. + * @deprecated since 5.0. Use CoreObject.flatten instead. */ flattenObject(obj: Record, useDotNotation?: boolean): Record { - const toReturn = {}; - - for (const name in obj) { - if (!Object.prototype.hasOwnProperty.call(obj, name)) { - continue; - } - - const value = obj[name]; - if (typeof value == 'object' && !Array.isArray(value)) { - const flatObject = this.flattenObject(value as Record); - for (const subName in flatObject) { - if (!Object.prototype.hasOwnProperty.call(flatObject, subName)) { - continue; - } - - const newName = useDotNotation ? name + '.' + subName : name + '[' + subName + ']'; - toReturn[newName] = flatObject[subName]; - } - } else { - toReturn[name] = value; - } - } - - return toReturn; + return CoreObject.flatten(obj, useDotNotation); } /** @@ -650,9 +581,10 @@ export class CoreUtilsProvider { * * @param object Variable. * @returns Type guard indicating if this is an object. + * @deprecated since 5.0. Use CoreObject.isObject instead. */ isObject(object: unknown): object is Record { - return typeof object === 'object' && object !== null; + return CoreObject.isObject(object); } /** @@ -672,22 +604,10 @@ export class CoreUtilsProvider { * @param array Array to search. * @param regex RegExp to apply to each string. * @returns Index of the first string that matches the RegExp. -1 if not found. + * @deprecated since 4.4. Use CoreArray.indexOfRegexp instead. */ indexOfRegexp(array: string[], regex: RegExp): number { - if (!array || !array.length) { - return -1; - } - - for (let i = 0; i < array.length; i++) { - const entry = array[i]; - const matches = entry.match(regex); - - if (matches && matches.length) { - return i; - } - } - - return -1; + return CoreArray.indexOfRegexp(array, regex); } /** @@ -787,9 +707,10 @@ export class CoreUtilsProvider { * @param array2 The second array. * @param [key] Key of the property that must be unique. If not specified, the whole entry. * @returns Merged array. + * @deprecated since 5.0. Use CoreArray.mergeWithoutDuplicates instead. */ mergeArraysWithoutDuplicates(array1: T[], array2: T[], key?: string): T[] { - return CoreArray.unique(array1.concat(array2), key) as T[]; + return CoreArray.mergeWithoutDuplicates(array1, array2, key); } /** @@ -855,9 +776,10 @@ export class CoreUtilsProvider { * * @param obj Object to convert. * @returns Array with the values of the object but losing the keys. + * @deprecated since 5.0. Use CoreObject.toArray instead. */ objectToArray(obj: Record): T[] { - return Object.keys(obj).map((key) => obj[key]); + return CoreObject.toArray(obj); } /** @@ -871,6 +793,7 @@ export class CoreUtilsProvider { * @param sortByKey True to sort keys alphabetically, false otherwise. Has priority over sortByValue. * @param sortByValue True to sort values alphabetically, false otherwise. * @returns Array of objects with the name & value of each property. + * @deprecated since 5.0. Use CoreObject.toArrayOfObjects instead. */ objectToArrayOfObjects< A extends Record = Record, @@ -882,53 +805,7 @@ export class CoreUtilsProvider { sortByKey?: boolean, sortByValue?: boolean, ): A[] { - // Get the entries from an object or primitive value. - const getEntries = (elKey: string, value: unknown): Record[] | unknown => { - if (value === undefined || value == null) { - // Filter undefined and null values. - return; - } else if (this.isObject(value)) { - // It's an object, return at least an entry for each property. - const keys = Object.keys(value); - let entries: unknown[] = []; - - keys.forEach((key) => { - const newElKey = elKey ? elKey + '[' + key + ']' : key; - const subEntries = getEntries(newElKey, value[key]); - - if (subEntries) { - entries = entries.concat(subEntries); - } - }); - - return entries; - } else { - // Not an object, return a single entry. - const entry = {}; - entry[keyName] = elKey; - entry[valueName] = value; - - return entry; - } - }; - - if (!obj) { - return []; - } - - // "obj" will always be an object, so "entries" will always be an array. - const entries = getEntries('', obj) as A[]; - if (sortByKey || sortByValue) { - return entries.sort((a, b) => { - if (sortByKey) { - return (a[keyName] as number) >= (b[keyName] as number) ? 1 : -1; - } else { - return (a[valueName] as number) >= (b[valueName] as number) ? 1 : -1; - } - }); - } - - return entries; + return CoreObject.toArrayOfObjects(obj, keyName, valueName, sortByKey, sortByValue); } /** @@ -940,6 +817,7 @@ export class CoreUtilsProvider { * @param valueName Name of the properties where the values are stored. * @param keyPrefix Key prefix if neededs to delete it. * @returns Object. + * @deprecated since 5.0. Use CoreObject.toKeyValueMap instead. */ objectToKeyValueMap( objects: Record[], @@ -947,15 +825,7 @@ export class CoreUtilsProvider { valueName: string, keyPrefix?: string, ): {[name: string]: T} { - const prefixSubstr = keyPrefix ? keyPrefix.length : 0; - const mapped = {}; - objects.forEach((item) => { - const keyValue = item[keyName] as string; - const key = prefixSubstr > 0 ? keyValue.substring(prefixSubstr) : keyValue; - mapped[key] = item[valueName]; - }); - - return mapped; + return CoreObject.toKeyValueMap(objects, keyName, valueName, keyPrefix); } /** @@ -964,29 +834,10 @@ export class CoreUtilsProvider { * @param object Object to convert. * @param removeEmpty Whether to remove params whose value is null/undefined. * @returns GET params. + * @deprecated since 5.0. Use CoreObject.toGetParams instead. */ objectToGetParams(object: Record, removeEmpty: boolean = true): string { - // First of all, flatten the object so all properties are in the first level. - const flattened = this.flattenObject(object); - let result = ''; - let joinChar = ''; - - for (const name in flattened) { - let value = flattened[name]; - - if (removeEmpty && (value === null || value === undefined)) { - continue; - } - - if (typeof value == 'boolean') { - value = value ? 1 : 0; - } - - result += joinChar + name + '=' + value; - joinChar = '&'; - } - - return result; + return CoreObject.toGetParams(object, removeEmpty); } /** @@ -995,6 +846,7 @@ export class CoreUtilsProvider { * @param data Object. * @param prefix Prefix to add. * @returns Prefixed object. + * @deprecated since 5.0. Not used anymore */ prefixKeys(data: Record, prefix: string): Record { const newObj = {}; @@ -1012,9 +864,10 @@ export class CoreUtilsProvider { * * @param enumeration Enumeration object. * @returns Keys of the enumeration. + * @deprecated since 5.0. Use CoreObject.enumKeys instead. */ enumKeys(enumeration: O): K[] { - return Object.keys(enumeration).filter(k => Number.isNaN(+k)) as K[]; + return CoreObject.enumKeys(enumeration); } /** @@ -1048,23 +901,14 @@ export class CoreUtilsProvider { * @param obj2 The second object or array. * @param key Key to check. * @returns Whether the two objects/arrays have the same value (or lack of one) for a given key. + * @deprecated since 5.0. Use CoreObject.sameAtKeyMissingIsBlank instead. */ sameAtKeyMissingIsBlank( obj1: Record | unknown[], obj2: Record | unknown[], key: string, ): boolean { - let value1 = obj1[key] !== undefined ? obj1[key] : ''; - let value2 = obj2[key] !== undefined ? obj2[key] : ''; - - if (typeof value1 == 'number' || typeof value1 == 'boolean') { - value1 = '' + value1; - } - if (typeof value2 == 'number' || typeof value2 == 'boolean') { - value2 = '' + value2; - } - - return value1 === value2; + return CoreObject.sameAtKeyMissingIsBlank(obj1, obj2, key); } /** @@ -1073,9 +917,11 @@ export class CoreUtilsProvider { * * @param obj Object to stringify. * @returns Stringified object. + * @deprecated since 5.0. Use CoreObject.sortAndStringify instead. */ sortAndStringify(obj: Record): string { - return JSON.stringify(this.sortProperties(obj)); + return CoreObject.sortAndStringify(obj); + } /** @@ -1083,19 +929,10 @@ export class CoreUtilsProvider { * * @param obj The object to sort. If it isn't an object, the original value will be returned. * @returns Sorted object. + * @deprecated since 5.0. Use CoreObject.sortProperties instead. */ sortProperties(obj: T): T { - if (obj != null && typeof obj == 'object' && !Array.isArray(obj)) { - // It's an object, sort it. - return Object.keys(obj).sort().reduce((accumulator, key) => { - // Always call sort with the value. If it isn't an object, the original value will be returned. - accumulator[key] = this.sortProperties(obj[key]); - - return accumulator; - }, {} as T); - } else { - return obj; - } + return CoreObject.sortProperties(obj); } /** @@ -1103,16 +940,10 @@ export class CoreUtilsProvider { * * @param obj The object to sort. If it isn't an object, the original value will be returned. * @returns Sorted object. + * @deprecated since 5.0. Use CoreObject.sortValues instead. */ sortValues(obj: T): T { - if (typeof obj == 'object' && !Array.isArray(obj)) { - // It's an object, sort it. Convert it to an array to be able to sort it and then convert it back to object. - const array = this.objectToArrayOfObjects(obj as Record, 'name', 'value', false, true); - - return this.objectToKeyValueMap(array, 'name', 'value') as unknown as T; - } else { - return obj; - } + return CoreObject.sortValues(obj); } /** diff --git a/src/core/services/ws.ts b/src/core/services/ws.ts index 379446944..119f4dd9d 100644 --- a/src/core/services/ws.ts +++ b/src/core/services/ws.ts @@ -170,7 +170,7 @@ export class CoreWSProvider { if (value == null) { // Skip null or undefined value. continue; - } else if (typeof value == 'object') { + } else if (typeof value === 'object') { // Object or array. value = this.convertValuesToString(value, stripUnicode); if (value == null) { @@ -498,7 +498,7 @@ export class CoreWSProvider { } // 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') { const message = CoreSites.isLoggedIn() ? Translate.instant('core.siteunavailablehelp', { site: CoreSites.getCurrentSite()?.siteUrl }) : Translate.instant('core.sitenotfoundhelp'); @@ -1090,7 +1090,7 @@ export class CoreWSProvider { }), }, }); - } else if (typeof data != 'object') { + } else if (typeof data !== 'object') { this.logger.warn('Upload file: Response of type "' + typeof data + '" received, expecting "object"'); throw await this.createCannotConnectSiteError(preSets.siteUrl, { diff --git a/src/core/singletons/array.ts b/src/core/singletons/array.ts index 71e885cb7..436d41b32 100644 --- a/src/core/singletons/array.ts +++ b/src/core/singletons/array.ts @@ -17,6 +17,62 @@ */ export class CoreArray { + // Avoid creating singleton instances. + private constructor() { + // Nothing to do. + } + + /** + * Converts an array of objects to an object, using a property of each entry as the key. + * It can also be used to convert an array of strings to an object where the keys are the elements of the array. + * E.g. [{id: 10, name: 'A'}, {id: 11, name: 'B'}] => {10: {id: 10, name: 'A'}, 11: {id: 11, name: 'B'}} + * + * @param array The array to convert. + * @param propertyName The name of the property to use as the key. If not provided, the whole item will be used. + * @param result Object where to put the properties. If not defined, a new object will be created. + * @returns The object. + */ + static toObject( + array: T[] = [], + propertyName?: string, + result: Record = {}, + ): Record { + for (const entry of array) { + const key = propertyName ? entry[propertyName] : entry; + + result[key] = entry; + } + + return result; + } + + /** + * Converts an array of objects to an indexed array, using a property of each entry as the key. + * Every entry will contain an array of the found objects of the property identifier. + * E.g. [{id: 10, name: 'A'}, {id: 10, name: 'B'}] => {10: [ {id: 10, name: 'A'}, {id: 10, name: 'B'} ] } + * + * @param array The array to convert. + * @param propertyName The name of the property to use as the key. If not provided, the whole item will be used. + * @param result Object where to put the properties. If not defined, a new object will be created. + * @returns The object. + */ + static toObjectMultiple( + array: T[] = [], + propertyName?: string, + result: Record = {}, + ): Record { + for (const entry of array) { + const key = propertyName ? entry[propertyName] : entry; + if (result[key] === undefined) { + result[key] = []; + } + + result[key].push(entry); + } + + return result; + } + /** * Flatten the first dimension of a multi-dimensional array. * @@ -93,4 +149,40 @@ export class CoreArray { }); } + /** + * Merge two arrays, removing duplicate values. + * + * @param array1 The first array. + * @param array2 The second array. + * @param [key] Key of the property that must be unique. If not specified, the whole entry. + * @returns Merged array. + */ + static mergeWithoutDuplicates(array1: T[], array2: T[], key?: string): T[] { + return CoreArray.unique(array1.concat(array2), key) as T[]; + } + + /** + * Gets the index of the first string that matches a regular expression. + * + * @param array Array to search. + * @param regex RegExp to apply to each string. + * @returns Index of the first string that matches the RegExp. -1 if not found. + */ + static indexOfRegexp(array: string[], regex: RegExp): number { + if (!array || !array.length) { + return -1; + } + + for (let i = 0; i < array.length; i++) { + const entry = array[i]; + const matches = entry.match(regex); + + if (matches && matches.length) { + return i; + } + } + + return -1; + } + } diff --git a/src/core/singletons/file-utils.ts b/src/core/singletons/file-utils.ts index 85e33ad5a..a7861eba0 100644 --- a/src/core/singletons/file-utils.ts +++ b/src/core/singletons/file-utils.ts @@ -44,7 +44,7 @@ export class CoreFileUtils { */ static 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 && + return !!(file && typeof file === 'object' && 'isFile' in file && 'filesystem' in file && 'toInternalURL' in file && 'copyTo' in file); } diff --git a/src/core/singletons/object.ts b/src/core/singletons/object.ts index 00e8dd65f..5ed742f1f 100644 --- a/src/core/singletons/object.ts +++ b/src/core/singletons/object.ts @@ -30,6 +30,11 @@ export type CoreObjectWithoutUndefined = Pretty<{ */ export class CoreObject { + // Avoid creating singleton instances. + private constructor() { + // Nothing to do. + } + /** * Returns a value of an object and deletes it from the object. * @@ -170,4 +175,335 @@ export class CoreObject { return cleanObj as CoreObjectWithoutUndefined; } + /** + * Tests to see whether two arrays or objects have the same value at a particular key. + * Missing values are replaced by '', and the values are compared with ===. + * Booleans and numbers are cast to string before comparing. + * + * @param obj1 The first object or array. + * @param obj2 The second object or array. + * @param key Key to check. + * @returns Whether the two objects/arrays have the same value (or lack of one) for a given key. + */ + static sameAtKeyMissingIsBlank( + obj1: Record | unknown[], + obj2: Record | unknown[], + key: string, + ): boolean { + let value1 = obj1[key] !== undefined ? obj1[key] : ''; + let value2 = obj2[key] !== undefined ? obj2[key] : ''; + + if (typeof value1 == 'number' || typeof value1 == 'boolean') { + value1 = '' + value1; + } + if (typeof value2 == 'number' || typeof value2 == 'boolean') { + value2 = '' + value2; + } + + return value1 === value2; + } + + /** + * Stringify an object, sorting the properties. It doesn't sort arrays, only object properties. E.g.: + * {b: 2, a: 1} -> '{"a":1,"b":2}' + * + * @param obj Object to stringify. + * @returns Stringified object. + */ + static sortAndStringify(obj: Record): string { + return JSON.stringify(CoreObject.sortProperties(obj)); + } + + /** + * Given an object, sort its properties and the properties of all the nested objects. + * + * @param obj The object to sort. If it isn't an object, the original value will be returned. + * @returns Sorted object. + */ + static sortProperties(obj: T): T { + if (obj != null && typeof obj === 'object' && !Array.isArray(obj)) { + // It's an object, sort it. + return Object.keys(obj).sort().reduce((accumulator, key) => { + // Always call sort with the value. If it isn't an object, the original value will be returned. + accumulator[key] = CoreObject.sortProperties(obj[key]); + + return accumulator; + }, {} as T); + } + + return obj; + } + + /** + * Given an object, sort its values. Values need to be primitive values, it cannot have subobjects. + * + * @param obj The object to sort. If it isn't an object, the original value will be returned. + * @returns Sorted object. + */ + static sortValues(obj: T): T { + if (typeof obj === 'object' && !Array.isArray(obj)) { + // It's an object, sort it. Convert it to an array to be able to sort it and then convert it back to object. + const array = CoreObject.toArrayOfObjects(obj as Record, 'name', 'value', false, true); + + return CoreObject.toKeyValueMap(array, 'name', 'value') as unknown as T; + } + + return obj; + } + + /** + * Converts an object into an array, losing the keys. + * + * @param obj Object to convert. + * @returns Array with the values of the object but losing the keys. + */ + static toArray(obj: Record): T[] { + return Object.keys(obj).map((key) => obj[key]); + } + + /** + * Converts an object into an array of objects, where each entry is an object containing + * the key and value of the original object. + * For example, it can convert {size: 2} into [{name: 'size', value: 2}]. + * + * @param obj Object to convert. + * @param keyName Name of the properties where to store the keys. + * @param valueName Name of the properties where to store the values. + * @param sortByKey True to sort keys alphabetically, false otherwise. Has priority over sortByValue. + * @param sortByValue True to sort values alphabetically, false otherwise. + * @returns Array of objects with the name & value of each property. + */ + static toArrayOfObjects< + A extends Record = Record, + O extends Record = Record + >( + obj: O, + keyName: string, + valueName: string, + sortByKey?: boolean, + sortByValue?: boolean, + ): A[] { + // Get the entries from an object or primitive value. + const getEntries = (elKey: string, value: unknown): Record[] | unknown => { + if (value === undefined || value == null) { + // Filter undefined and null values. + return; + } else if (CoreObject.isObject(value)) { + // It's an object, return at least an entry for each property. + const keys = Object.keys(value); + let entries: unknown[] = []; + + keys.forEach((key) => { + const newElKey = elKey ? elKey + '[' + key + ']' : key; + const subEntries = getEntries(newElKey, value[key]); + + if (subEntries) { + entries = entries.concat(subEntries); + } + }); + + return entries; + } else { + // Not an object, return a single entry. + const entry = {}; + entry[keyName] = elKey; + entry[valueName] = value; + + return entry; + } + }; + + if (!obj) { + return []; + } + + // "obj" will always be an object, so "entries" will always be an array. + const entries = getEntries('', obj) as A[]; + if (sortByKey || sortByValue) { + return entries.sort((a, b) => { + if (sortByKey) { + return (a[keyName] as number) >= (b[keyName] as number) ? 1 : -1; + } else { + return (a[valueName] as number) >= (b[valueName] as number) ? 1 : -1; + } + }); + } + + return entries; + } + + /** + * Converts an array of objects into an object with key and value. The opposite of objectToArrayOfObjects. + * For example, it can convert [{name: 'size', value: 2}] into {size: 2}. + * + * @param objects List of objects to convert. + * @param keyName Name of the properties where the keys are stored. + * @param valueName Name of the properties where the values are stored. + * @param keyPrefix Key prefix if neededs to delete it. + * @returns Object. + */ + static toKeyValueMap( + objects: Record[], + keyName: string, + valueName: string, + keyPrefix?: string, + ): {[name: string]: T} { + const prefixSubstr = keyPrefix ? keyPrefix.length : 0; + const mapped = {}; + objects.forEach((item) => { + const keyValue = item[keyName] as string; + const key = prefixSubstr > 0 ? keyValue.substring(prefixSubstr) : keyValue; + mapped[key] = item[valueName]; + }); + + return mapped; + } + + /** + * Convert an object to a format of GET param. E.g.: {a: 1, b: 2} -> a=1&b=2 + * + * @param object Object to convert. + * @param removeEmpty Whether to remove params whose value is null/undefined. + * @returns GET params. + */ + static toGetParams(object: Record, removeEmpty: boolean = true): string { + // First of all, flatten the object so all properties are in the first level. + const flattened = CoreObject.flatten(object); + let result = ''; + let joinChar = ''; + + for (const name in flattened) { + let value = flattened[name]; + + if (removeEmpty && (value === null || value === undefined)) { + continue; + } + + if (typeof value === 'boolean') { + value = value ? 1 : 0; + } + + result += joinChar + name + '=' + value; + joinChar = '&'; + } + + return result; + } + + /** + * Function to enumerate enum keys. + * + * @param enumeration Enumeration object. + * @returns Keys of the enumeration. + */ + static enumKeys(enumeration: O): K[] { + return Object.keys(enumeration).filter(k => Number.isNaN(+k)) as K[]; + } + + /** + * Check if a value is an object. + * + * @param object Variable. + * @returns Type guard indicating if this is an object. + */ + static isObject(object: unknown): object is Record { + return typeof object === 'object' && object !== null; + } + + /** + * Flatten an object, moving subobjects' properties to the first level. + * It supports 2 notations: dot notation and square brackets. + * E.g.: {a: {b: 1, c: 2}, d: 3} -> {'a.b': 1, 'a.c': 2, d: 3} + * + * @param obj Object to flatten. + * @param useDotNotation Whether to use dot notation '.' or square brackets '['. + * @returns Flattened object. + */ + static flatten(obj: Record, useDotNotation?: boolean): Record { + const toReturn = {}; + + for (const name in obj) { + if (!Object.prototype.hasOwnProperty.call(obj, name)) { + continue; + } + + const value = obj[name]; + if (typeof value === 'object' && !Array.isArray(value)) { + const flatObject = CoreObject.flatten(value as Record); + for (const subName in flatObject) { + if (!Object.prototype.hasOwnProperty.call(flatObject, subName)) { + continue; + } + + const newName = useDotNotation ? name + '.' + subName : name + '[' + subName + ']'; + toReturn[newName] = flatObject[subName]; + } + } else { + toReturn[name] = value; + } + } + + return toReturn; + } + + /** + * Compare two objects. This function won't compare functions and proto properties, it's a basic compare. + * Also, this will only check if itemA's properties are in itemB with same value. This function will still + * return true if itemB has more properties than itemA. + * + * @param itemA First object. + * @param itemB Second object. + * @param maxLevels Number of levels to reach if 2 objects are compared. + * @param level Current deep level (when comparing objects). + * @param undefinedIsNull True if undefined is equal to null. Defaults to true. + * @returns Whether both items are equal. + */ + static basicLeftCompare( + itemA: any, // eslint-disable-line @typescript-eslint/no-explicit-any + itemB: any, // eslint-disable-line @typescript-eslint/no-explicit-any + maxLevels: number = 0, + level: number = 0, + undefinedIsNull: boolean = true, + ): boolean { + if (typeof itemA == 'function' || typeof itemB == 'function') { + return true; // Don't compare functions. + } + + if (typeof itemA === 'object' && typeof itemB === 'object') { + if (level >= maxLevels) { + return true; // Max deep reached. + } + + let equal = true; + for (const name in itemA) { + const value = itemA[name]; + if (name == '$$hashKey') { + // Ignore $$hashKey property since it's a "calculated" property. + continue; + } + + if (!CoreObject.basicLeftCompare(value, itemB[name], maxLevels, level + 1)) { + equal = false; + } + } + + return equal; + } + + if (undefinedIsNull && ( + (itemA === undefined && itemB === null) || (itemA === null && itemB === undefined))) { + return true; + } + + // We'll treat "2" and 2 as the same value. + const floatA = parseFloat(itemA); + const floatB = parseFloat(itemB); + + if (!isNaN(floatA) && !isNaN(floatB)) { + return floatA == floatB; + } + + return itemA === itemB; + } + }