diff --git a/src/addons/badges/services/handlers/user.ts b/src/addons/badges/services/handlers/user.ts index f2cb27bac..52e44fb69 100644 --- a/src/addons/badges/services/handlers/user.ts +++ b/src/addons/badges/services/handlers/user.ts @@ -14,7 +14,6 @@ import { Injectable } from '@angular/core'; import { CoreCourseUserAdminOrNavOptionIndexed } from '@features/courses/services/courses'; -import { CoreUserProfile } from '@features/user/services/user'; import { CoreUserDelegateService, CoreUserProfileHandler, CoreUserProfileHandlerData } from '@features/user/services/user-delegate'; import { CoreNavigator } from '@services/navigator'; import { makeSingleton } from '@singletons'; @@ -42,13 +41,11 @@ export class AddonBadgesUserHandlerService implements CoreUserProfileHandler { /** * Check if handler is enabled for this user in this context. * - * @param user User to check. * @param courseId Course ID. * @param navOptions Course navigation options for current user. See CoreCoursesProvider.getUserNavigationOptions. * @return True if enabled, false otherwise. */ - async isEnabledForUser( - user: CoreUserProfile, + async isEnabledForCourse( courseId: number, navOptions?: CoreCourseUserAdminOrNavOptionIndexed, ): Promise { diff --git a/src/addons/blog/services/handlers/user.ts b/src/addons/blog/services/handlers/user.ts index f2e625f58..5c6d08726 100644 --- a/src/addons/blog/services/handlers/user.ts +++ b/src/addons/blog/services/handlers/user.ts @@ -35,13 +35,6 @@ export class AddonBlogUserHandlerService implements CoreUserProfileHandler { return AddonBlog.isPluginEnabled(); } - /** - * @inheritdoc - */ - async isEnabledForUser(): Promise { - return true; - } - /** * @inheritdoc */ diff --git a/src/addons/coursecompletion/services/coursecompletion.ts b/src/addons/coursecompletion/services/coursecompletion.ts index cee944029..21898f3c6 100644 --- a/src/addons/coursecompletion/services/coursecompletion.ts +++ b/src/addons/coursecompletion/services/coursecompletion.ts @@ -164,9 +164,9 @@ export class AddonCourseCompletionProvider { * @param preferCache True if shouldn't call WS if data is cached, false otherwise. * @return Promise resolved with true if plugin is enabled, rejected or resolved with false otherwise. */ - async isPluginViewEnabledForCourse(courseId: number, preferCache: boolean = true): Promise { + async isPluginViewEnabledForCourse(courseId?: number, preferCache: boolean = true): Promise { if (!courseId) { - throw new CoreError('No courseId provided'); + return false; } const course = await CoreCourses.getUserCourse(courseId, preferCache); diff --git a/src/addons/coursecompletion/services/handlers/user.ts b/src/addons/coursecompletion/services/handlers/user.ts index 1f913caf1..172073c60 100644 --- a/src/addons/coursecompletion/services/handlers/user.ts +++ b/src/addons/coursecompletion/services/handlers/user.ts @@ -13,11 +13,10 @@ // limitations under the License. import { Injectable } from '@angular/core'; -import { CoreUserProfile, CoreUserProvider } from '@features/user/services/user'; +import { CoreUserProfile } from '@features/user/services/user'; import { CoreUserProfileHandler, CoreUserDelegateService, CoreUserProfileHandlerData } from '@features/user/services/user-delegate'; import { CoreNavigator } from '@services/navigator'; import { makeSingleton } from '@singletons'; -import { CoreEvents } from '@singletons/events'; import { AddonCourseCompletion } from '../coursecompletion'; /** @@ -29,20 +28,7 @@ export class AddonCourseCompletionUserHandlerService implements CoreUserProfileH name = 'AddonCourseCompletion'; type = CoreUserDelegateService.TYPE_NEW_PAGE; priority = 200; - - protected enabledCache = {}; - - constructor() { - CoreEvents.on(CoreEvents.LOGOUT, () => { - this.enabledCache = {}; - }); - - CoreEvents.on(CoreUserProvider.PROFILE_REFRESHED, (data) => { - const cacheKey = data.userId + '-' + data.courseId; - - delete this.enabledCache[cacheKey]; - }); - } + cacheEnabled = true; /** * @inheritdoc @@ -51,29 +37,18 @@ export class AddonCourseCompletionUserHandlerService implements CoreUserProfileH return AddonCourseCompletion.isPluginViewEnabled(); } + /** + * @inheritdoc + */ + async isEnabledForCourse(courseId?: number): Promise { + return AddonCourseCompletion.isPluginViewEnabledForCourse(courseId); + } + /** * @inheritdoc */ async isEnabledForUser(user: CoreUserProfile, courseId?: number): Promise { - if (!courseId) { - return false; - } - - const courseEnabled = await AddonCourseCompletion.isPluginViewEnabledForCourse(courseId); - // If is not enabled in the course, is not enabled for the user. - if (!courseEnabled) { - return false; - } - - const cacheKey = user.id + '-' + courseId; - if (typeof this.enabledCache[cacheKey] !== 'undefined') { - return this.enabledCache[cacheKey]; - } - - const enabled = await AddonCourseCompletion.isPluginViewEnabledForUser(courseId, user.id); - this.enabledCache[cacheKey] = enabled; - - return enabled; + return await AddonCourseCompletion.isPluginViewEnabledForUser(courseId!, user.id); } /** diff --git a/src/addons/messages/services/handlers/user-send-message.ts b/src/addons/messages/services/handlers/user-send-message.ts index d0566d7cd..bfb9f3b79 100644 --- a/src/addons/messages/services/handlers/user-send-message.ts +++ b/src/addons/messages/services/handlers/user-send-message.ts @@ -40,6 +40,13 @@ export class AddonMessagesSendMessageUserHandlerService implements CoreUserProfi return AddonMessages.isPluginEnabled(); } + /** + * @inheritdoc + */ + async isEnabledForCourse(): Promise { + return !!CoreSites.getCurrentSite(); + } + /** * Check if handler is enabled for this user in this context. * @@ -47,14 +54,10 @@ export class AddonMessagesSendMessageUserHandlerService implements CoreUserProfi * @return Promise resolved with true if enabled, resolved with false otherwise. */ async isEnabledForUser(user: CoreUserProfile): Promise { - const currentSite = CoreSites.getCurrentSite(); - - if (!currentSite) { - return false; - } + const currentSite = CoreSites.getCurrentSite()!; // From 3.7 you can send messages to yourself. - return user.id != currentSite.getUserId() || currentSite.isVersionGreaterEqualThan('3.7'); + return user.id != CoreSites.getCurrentSiteUserId() || currentSite.isVersionGreaterEqualThan('3.7'); } /** diff --git a/src/core/features/grades/services/grades.ts b/src/core/features/grades/services/grades.ts index a160ba461..2e40eab8f 100644 --- a/src/core/features/grades/services/grades.ts +++ b/src/core/features/grades/services/grades.ts @@ -329,7 +329,7 @@ export class CoreGradesProvider { * @param siteId Site ID. If not defined, current site. * @return Promise resolved with true if plugin is enabled, rejected or resolved with false otherwise. */ - async isPluginEnabledForCourse(courseId: number, siteId?: string): Promise { + async isPluginEnabledForCourse(courseId?: number, siteId?: string): Promise { if (!courseId) { return false; } diff --git a/src/core/features/grades/services/handlers/user.ts b/src/core/features/grades/services/handlers/user.ts index f6c3fa749..544044018 100644 --- a/src/core/features/grades/services/handlers/user.ts +++ b/src/core/features/grades/services/handlers/user.ts @@ -34,73 +34,31 @@ export class CoreGradesUserHandlerService implements CoreUserProfileHandler { name = 'CoreGrades:viewGrades'; priority = 400; type = CoreUserDelegateService.TYPE_NEW_PAGE; - viewGradesEnabledCache = {}; + cacheEnabled = true; /** - * Clear view grades cache. - * If a courseId and userId are specified, it will only delete the entry for that user and course. - * - * @param courseId Course ID. - * @param userId User ID. - */ - clearViewGradesCache(courseId?: number, userId?: number): void { - if (courseId && userId) { - delete this.viewGradesEnabledCache[this.getCacheKey(courseId, userId)]; - } else { - this.viewGradesEnabledCache = {}; - } - } - - /** - * Get a cache key to identify a course and a user. - * - * @param courseId Course ID. - * @param userId User ID. - * @return Cache key. - */ - protected getCacheKey(courseId: number, userId: number): string { - return courseId + '#' + userId; - } - - /** - * Check if handler is enabled. - * - * @return Always enabled. + * @inheritdoc */ async isEnabled(): Promise { return true; } /** - * Check if handler is enabled for this user in this context. - * - * @param user User to check. - * @param courseId Course ID. - * @return Promise resolved with true if enabled, resolved with false otherwise. + * @inheritdoc */ - async isEnabledForUser(user: CoreUserProfile, courseId: number): Promise { - const cacheKey = this.getCacheKey(courseId, user.id); - const cache = this.viewGradesEnabledCache[cacheKey]; - - if (typeof cache != 'undefined') { - return cache; - } - - let enabled = await CoreUtils.ignoreErrors(CoreGrades.isPluginEnabledForCourse(courseId), false); - - if (enabled) { - enabled = await CoreUtils.promiseWorks(CoreGrades.getCourseGradesTable(courseId, user.id)); - } - - this.viewGradesEnabledCache[cacheKey] = true; - - return enabled; + async isEnabledForCourse(courseId?: number): Promise { + return CoreUtils.ignoreErrors(CoreGrades.isPluginEnabledForCourse(courseId), false); } /** - * Returns the data needed to render the handler. - * - * @return Data needed to render the handler. + * @inheritdoc + */ + async isEnabledForUser(user: CoreUserProfile, courseId?: number): Promise { + return CoreUtils.promiseWorks(CoreGrades.getCourseGradesTable(courseId!, user.id)); + } + + /** + * @inheritdoc */ getDisplayData(): CoreUserProfileHandlerData { return { diff --git a/src/core/features/siteplugins/classes/handlers/user-handler.ts b/src/core/features/siteplugins/classes/handlers/user-handler.ts index 86978a13e..315e198da 100644 --- a/src/core/features/siteplugins/classes/handlers/user-handler.ts +++ b/src/core/features/siteplugins/classes/handlers/user-handler.ts @@ -55,24 +55,12 @@ export class CoreSitePluginsUserProfileHandler extends CoreSitePluginsBaseHandle /** * @inheritdoc */ - async isEnabledForUser( - user: CoreUserProfile, + async isEnabledForCourse( courseId?: number, ): Promise { - // First check if it's enabled for the user. - const enabledForUser = CoreSitePlugins.isHandlerEnabledForUser( - user.id, - this.handlerSchema.restricttocurrentuser, - this.initResult?.restrict, - ); - - if (!enabledForUser) { - return false; - } - courseId = courseId || CoreSites.getCurrentSiteHomeId(); - // Enabled for user, check if it's enabled for the course. + // Check if it's enabled for the course. return CoreSitePlugins.isHandlerEnabledForCourse( courseId, this.handlerSchema.restricttoenrolledcourses, @@ -80,6 +68,19 @@ export class CoreSitePluginsUserProfileHandler extends CoreSitePluginsBaseHandle ); } + /** + * @inheritdoc + */ + async isEnabledForUser( + user: CoreUserProfile, + ): Promise { + return CoreSitePlugins.isHandlerEnabledForUser( + user.id, + this.handlerSchema.restricttocurrentuser, + this.initResult?.restrict, + ); + } + /** * @inheritdoc */ diff --git a/src/core/features/user/services/handlers/profile-mail.ts b/src/core/features/user/services/handlers/profile-mail.ts index 2af4d8f8f..d2c243643 100644 --- a/src/core/features/user/services/handlers/profile-mail.ts +++ b/src/core/features/user/services/handlers/profile-mail.ts @@ -31,35 +31,23 @@ export class CoreUserProfileMailHandlerService implements CoreUserProfileHandler type = CoreUserDelegateService.TYPE_COMMUNICATION; /** - * Check if handler is enabled. - * - * @return Always enabled. + * @inheritdoc */ async isEnabled(): Promise { return true; } /** - * Check if handler is enabled for this user in this context. - * - * @param user User to check. - * @param courseId Course ID. - * @param navOptions Course navigation options for current user. See CoreCoursesProvider.getUserNavigationOptions. - * @param admOptions Course admin options for current user. See CoreCoursesProvider.getUserAdministrationOptions. - * @return Promise resolved with true if enabled, resolved with false otherwise. + * @inheritdoc */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars - async isEnabledForUser(user: CoreUserProfile, courseId: number, navOptions?: unknown, admOptions?: unknown): Promise { + async isEnabledForUser(user: CoreUserProfile): Promise { return user.id != CoreSites.getCurrentSiteUserId() && !!user.email; } /** - * Returns the data needed to render the handler. - * - * @return Data needed to render the handler. + * @inheritdoc */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars - getDisplayData(user: CoreUserProfile, courseId: number): CoreUserProfileHandlerData { + getDisplayData(): CoreUserProfileHandlerData { return { icon: 'mail', title: 'core.user.sendemail', diff --git a/src/core/features/user/services/user-delegate.ts b/src/core/features/user/services/user-delegate.ts index 1f2205369..551e22ad9 100644 --- a/src/core/features/user/services/user-delegate.ts +++ b/src/core/features/user/services/user-delegate.ts @@ -18,7 +18,7 @@ import { Subject, BehaviorSubject } from 'rxjs'; import { CoreDelegate, CoreDelegateHandler } from '@classes/delegate'; import { CoreUtils } from '@services/utils/utils'; import { CoreEvents } from '@singletons/events'; -import { CoreUserProfile } from './user'; +import { CoreUserProfile, CoreUserProvider } from './user'; import { makeSingleton } from '@singletons'; import { CoreCourses, CoreCourseUserAdminOrNavOptionIndexed } from '@features/courses/services/courses'; import { CoreSites } from '@services/sites'; @@ -42,21 +42,36 @@ export interface CoreUserProfileHandler extends CoreDelegateHandler { type: string; /** - * Whether or not the handler is enabled for a user. + * If isEnabledForUser Cache should be enabled. + */ + cacheEnabled?: boolean; + + /** + * Whether or not the handler is enabled for a course. * - * @param user User object. * @param courseId Course ID where to show. * @param navOptions Navigation options for the course. * @param admOptions Admin options for the course. * @return Whether or not the handler is enabled for a user. */ - isEnabledForUser( - user: CoreUserProfile, + isEnabledForCourse?( courseId?: number, navOptions?: CoreCourseUserAdminOrNavOptionIndexed, admOptions?: CoreCourseUserAdminOrNavOptionIndexed, ): Promise; + /** + * Whether or not the handler is enabled for a user. + * + * @param user User object. + * @param courseId Course ID where to show. + * @return Whether or not the handler is enabled for a user. + */ + isEnabledForUser?( + user: CoreUserProfile, + courseId?: number, + ): Promise; + /** * Returns the data needed to render the handler. * @@ -156,6 +171,11 @@ export class CoreUserDelegateService extends CoreDelegate> = {}; + protected featurePrefix = 'CoreUserDelegate_'; // Hold the handlers and the observable to notify them for each user. @@ -186,6 +206,14 @@ export class CoreUserDelegateService extends CoreDelegate { + this.clearHandlerCache(); + }); + + CoreEvents.on(CoreUserProvider.PROFILE_REFRESHED, (data) => { + this.clearHandlerCache(data.courseId, data.userId); + }); } /** @@ -267,7 +295,7 @@ export class CoreUserDelegateService extends CoreDelegate { + if (handler.isEnabledForCourse) { + const enabledOnCourse = await handler.isEnabledForCourse(courseId, navOptions, admOptions); + + if (!enabledOnCourse) { + // If is not enabled in the course, is not enabled for the user. + // Do not cache if this is false. + return false; + } + } + + if (!handler.cacheEnabled) { + if (!handler.isEnabledForUser) { + // True by default. + return true; + } + + return handler.isEnabledForUser(user, courseId); + } + + if (typeof this.enabledForUserCache[handler.name] == 'undefined') { + this.enabledForUserCache[handler.name] = {}; + } + + const cacheKey = this.getCacheKey(courseId, user.id); + const cache = this.enabledForUserCache[handler.name][cacheKey]; + + if (typeof cache != 'undefined') { + return cache; + } + + let enabled = true; // Default value. + if (handler.isEnabledForUser) { + enabled = await handler.isEnabledForUser(user, courseId); + } + + this.enabledForUserCache[handler.name][cacheKey] = enabled; + + return enabled; + } + + /** + * Clear handler enabled for user cache. + * If a courseId and userId are specified, it will only delete the entry for that user and course. + * + * @param courseId Course ID. + * @param userId User ID. + */ + protected clearHandlerCache(courseId?: number, userId?: number): void { + if (courseId && userId) { + Object.keys(this.enabledHandlers).forEach((name) => { + delete this.enabledForUserCache[name][this.getCacheKey(courseId, userId)]; + }); + } else { + this.enabledForUserCache = {}; + } + } + + /** + * Get a cache key to identify a course and a user. + * + * @param courseId Course ID. + * @param userId User ID. + * @return Cache key. + */ + protected getCacheKey(courseId = 0, userId = 0): string { + return courseId + '#' + userId; + } + } export const CoreUserDelegate = makeSingleton(CoreUserDelegateService);