diff --git a/src/core/siteaddons/classes/base-handler.ts b/src/core/siteaddons/classes/base-handler.ts new file mode 100644 index 000000000..bfdd31ef9 --- /dev/null +++ b/src/core/siteaddons/classes/base-handler.ts @@ -0,0 +1,32 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { CoreDelegateHandler } from '../../../classes/delegate'; + +/** + * Super class for handlers for site addons. + */ +export class CoreSiteAddonsBaseHandler implements CoreDelegateHandler { + + constructor(public name: string) { } + + /** + * Whether or not the handler is enabled on a site level. + * + * @return {boolean|Promise} A boolean, or a promise resolved with a boolean, indicating if the handler is enabled. + */ + isEnabled(): boolean | Promise { + return true; + } +} diff --git a/src/core/siteaddons/classes/course-format-handler.ts b/src/core/siteaddons/classes/course-format-handler.ts new file mode 100644 index 000000000..fddf165a2 --- /dev/null +++ b/src/core/siteaddons/classes/course-format-handler.ts @@ -0,0 +1,74 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Injector } from '@angular/core'; +import { CoreCourseFormatHandler } from '../../course/providers/format-delegate'; +import { CoreSiteAddonsBaseHandler } from './base-handler'; +import { CoreSiteAddonsCourseFormatComponent } from '../components/course-format/course-format'; + +/** + * Handler to support a course format using a site addon. + */ +export class CoreSiteAddonsCourseFormatHandler extends CoreSiteAddonsBaseHandler implements CoreCourseFormatHandler { + + constructor(name: string, protected handlerSchema: any) { + super(name); + } + + /** + * Whether it allows seeing all sections at the same time. Defaults to true. + * + * @param {any} course The course to check. + * @type {boolean} Whether it can view all sections. + */ + canViewAllSections(course: any): boolean { + return typeof this.handlerSchema.canviewallsections != 'undefined' ? this.handlerSchema.canviewallsections : true; + } + + /** + * Whether the option to enable section/module download should be displayed. Defaults to true. + * + * @param {any} course The course to check. + * @type {boolean} Whether the option to enable section/module download should be displayed. + */ + displayEnableDownload(course: any): boolean { + return typeof this.handlerSchema.displayenabledownload != 'undefined' ? this.handlerSchema.displayenabledownload : true; + } + + /** + * Whether the default section selector should be displayed. Defaults to true. + * + * @param {any} course The course to check. + * @type {boolean} Whether the default section selector should be displayed. + */ + displaySectionSelector(course: any): boolean { + return typeof this.handlerSchema.displaysectionselector != 'undefined' ? this.handlerSchema.displaysectionselector : true; + } + + /** + * Return the Component to use to display the course format instead of using the default one. + * Use it if you want to display a format completely different from the default one. + * If you want to customize the default format there are several methods to customize parts of it. + * It's recommended to return the class of the component, but you can also return an instance of the component. + * + * @param {Injector} injector Injector. + * @param {any} course The course to render. + * @return {any|Promise} The component (or promise resolved with component) to use, undefined if not found. + */ + getCourseFormatComponent(injector: Injector, course: any): any | Promise { + if (this.handlerSchema.method) { + return CoreSiteAddonsCourseFormatComponent; + } + } +} diff --git a/src/core/siteaddons/classes/course-option-handler.ts b/src/core/siteaddons/classes/course-option-handler.ts new file mode 100644 index 000000000..b0041f401 --- /dev/null +++ b/src/core/siteaddons/classes/course-option-handler.ts @@ -0,0 +1,80 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Injector } from '@angular/core'; +import { CoreSiteAddonsProvider } from '../providers/siteaddons'; +import { CoreCourseOptionsHandler, CoreCourseOptionsHandlerData } from '../../course/providers/options-delegate'; +import { CoreSiteAddonsBaseHandler } from './base-handler'; +import { CoreSiteAddonsCourseOptionComponent } from '../components/course-option/course-option'; + +/** + * Handler to display a site addon in course options. + */ +export class CoreSiteAddonsCourseOptionHandler extends CoreSiteAddonsBaseHandler implements CoreCourseOptionsHandler { + priority: number; + + constructor(name: string, protected title: string, protected addon: any, protected handlerSchema: any, + protected bootstrapResult: any, protected siteAddonsProvider: CoreSiteAddonsProvider) { + super(name); + + this.priority = handlerSchema.priority; + } + + /** + * Whether or not the handler is enabled for a certain course. + * + * @param {number} courseId The course ID. + * @param {any} accessData Access type and data. Default, guest, ... + * @param {any} [navOptions] Course navigation options for current user. See CoreCoursesProvider.getUserNavigationOptions. + * @param {any} [admOptions] Course admin options for current user. See CoreCoursesProvider.getUserAdministrationOptions. + * @return {boolean|Promise} True or promise resolved with true if enabled. + */ + isEnabledForCourse(courseId: number, accessData: any, navOptions?: any, admOptions?: any): boolean | Promise { + return this.siteAddonsProvider.isHandlerEnabledForCourse( + courseId, this.handlerSchema.restricttoenrolledcourses, this.bootstrapResult.restrict); + } + + /** + * Returns the data needed to render the handler. + * + * @param {Injector} injector Injector. + * @param {number} courseId The course ID. + * @return {CoreCourseOptionsHandlerData|Promise} Data or promise resolved with the data. + */ + getDisplayData(injector: Injector, courseId: number): CoreCourseOptionsHandlerData | Promise { + return { + title: this.title, + class: this.handlerSchema.displaydata.class, + component: CoreSiteAddonsCourseOptionComponent, + componentData: { + handlerUniqueName: this.name + } + }; + } + + /** + * Called when a course is downloaded. It should prefetch all the data to be able to see the addon in offline. + * + * @param {any} course The course. + * @return {Promise} Promise resolved when done. + */ + prefetch(course: any): Promise { + const args = { + courseid: course.id, + }, + component = this.addon.component; + + return this.siteAddonsProvider.prefetchFunctions(component, args, this.handlerSchema, course.id, undefined, true); + } +} diff --git a/src/core/siteaddons/classes/main-menu-handler.ts b/src/core/siteaddons/classes/main-menu-handler.ts new file mode 100644 index 000000000..a66a01788 --- /dev/null +++ b/src/core/siteaddons/classes/main-menu-handler.ts @@ -0,0 +1,50 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { CoreMainMenuHandler, CoreMainMenuHandlerData } from '../../mainmenu/providers/delegate'; +import { CoreSiteAddonsBaseHandler } from './base-handler'; + +/** + * Handler to display a site addon in the main menu. + */ +export class CoreSiteAddonsMainMenuHandler extends CoreSiteAddonsBaseHandler implements CoreMainMenuHandler { + priority: number; + + constructor(name: string, protected title: string, protected addon: any, protected handlerSchema: any, + protected bootstrapResult: any) { + super(name); + + this.priority = handlerSchema.priority; + } + + /** + * Returns the data needed to render the handler. + * + * @return {CoreMainMenuHandlerData} Data. + */ + getDisplayData(): CoreMainMenuHandlerData { + return { + title: this.title, + icon: this.handlerSchema.displaydata.icon, + class: this.handlerSchema.displaydata.class, + page: 'CoreSiteAddonsAddonPage', + pageParams: { + title: this.title, + component: this.addon.component, + method: this.handlerSchema.method, + bootstrapResult: this.bootstrapResult + } + }; + } +} diff --git a/src/core/siteaddons/classes/module-handler.ts b/src/core/siteaddons/classes/module-handler.ts new file mode 100644 index 000000000..29bfb911b --- /dev/null +++ b/src/core/siteaddons/classes/module-handler.ts @@ -0,0 +1,74 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Injector } from '@angular/core'; +import { NavController, NavOptions } from 'ionic-angular'; +import { CoreCourseModuleHandler, CoreCourseModuleHandlerData } from '../../course/providers/module-delegate'; +import { CoreSiteAddonsBaseHandler } from './base-handler'; +import { CoreSiteAddonsModuleIndexComponent } from '../components/module-index/module-index'; + +/** + * Handler to support a module using a site addon. + */ +export class CoreSiteAddonsModuleHandler extends CoreSiteAddonsBaseHandler implements CoreCourseModuleHandler { + priority: number; + + constructor(name: string, protected handlerSchema: any) { + super(name); + } + + /** + * Get the data required to display the module in the course contents view. + * + * @param {any} module The module object. + * @param {number} courseId The course ID. + * @param {number} sectionId The section ID. + * @return {CoreCourseModuleHandlerData} Data to render the module. + */ + getData(module: any, courseId: number, sectionId: number): CoreCourseModuleHandlerData { + const hasOffline = !!(this.handlerSchema.offlinefunctions && Object.keys(this.handlerSchema.offlinefunctions).length), + showDowloadButton = this.handlerSchema.downloadbutton; + + return { + title: module.name, + icon: this.handlerSchema.displaydata.icon, + class: this.handlerSchema.displaydata.class, + showDownloadButton: typeof showDowloadButton != 'undefined' ? showDowloadButton : hasOffline, + action: (event: Event, navCtrl: NavController, module: any, courseId: number, options: NavOptions): void => { + event.preventDefault(); + event.stopPropagation(); + + navCtrl.push('CoreSiteAddonsModuleIndexPage', { + title: module.name, + module: module, + courseId: courseId + }, options); + } + }; + } + + /** + * Get the component to render the module. This is needed to support singleactivity course format. + * The component returned must implement CoreCourseModuleMainComponent. + * It's recommended to return the class of the component, but you can also return an instance of the component. + * + * @param {Injector} injector Injector. + * @param {any} course The course object. + * @param {any} module The module object. + * @return {any|Promise} The component (or promise resolved with component) to use, undefined if not found. + */ + getMainComponent(injector: Injector, course: any, module: any): any | Promise { + return CoreSiteAddonsModuleIndexComponent; + } +} diff --git a/src/core/siteaddons/classes/user-handler.ts b/src/core/siteaddons/classes/user-handler.ts new file mode 100644 index 000000000..482af10db --- /dev/null +++ b/src/core/siteaddons/classes/user-handler.ts @@ -0,0 +1,100 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { NavController } from 'ionic-angular'; +import { CoreUserDelegate, CoreUserProfileHandler, CoreUserProfileHandlerData } from '../../user/providers/user-delegate'; +import { CoreSiteAddonsProvider } from '../providers/siteaddons'; +import { CoreSiteAddonsBaseHandler } from './base-handler'; + +/** + * Handler to display a site addon in the user profile. + */ +export class CoreSiteAddonsUserProfileHandler extends CoreSiteAddonsBaseHandler implements CoreUserProfileHandler { + /** + * The highest priority is displayed first. + * @type {number} + */ + priority: number; + + /** + * A type should be specified among these: + * - TYPE_COMMUNICATION: will be displayed under the user avatar. Should have icon. Spinner not used. + * - TYPE_NEW_PAGE: will be displayed as a list of items. Should have icon. Spinner not used. + * Default value if none is specified. + * - TYPE_ACTION: will be displayed as a button and should not redirect to any state. Spinner use is recommended. + * @type {string} + */ + type: string; + + constructor(name: string, protected title: string, protected addon: any, protected handlerSchema: any, + protected bootstrapResult: any, protected siteAddonsProvider: CoreSiteAddonsProvider) { + super(name); + + this.priority = handlerSchema.priority; + + // Only support TYPE_COMMUNICATION and TYPE_NEW_PAGE. + this.type = handlerSchema.type != CoreUserDelegate.TYPE_COMMUNICATION ? + CoreUserDelegate.TYPE_NEW_PAGE : CoreUserDelegate.TYPE_COMMUNICATION; + } + + /** + * Whether or not the handler is enabled for a user. + * @param {any} user User object. + * @param {number} courseId Course ID where to show. + * @param {any} [navOptions] Navigation options for the course. + * @param {any} [admOptions] Admin options for the course. + * @return {boolean|Promise} Whether or not the handler is enabled for a user. + */ + isEnabledForUser(user: any, courseId: number, navOptions?: any, admOptions?: any): boolean | Promise { + // First check if it's enabled for the user. + const enabledForUser = this.siteAddonsProvider.isHandlerEnabledForUser(user.id, this.handlerSchema.restricttocurrentuser, + this.bootstrapResult.restrict); + if (!enabledForUser) { + return false; + } + + // Enabled for user, check if it's enabled for the course. + return this.siteAddonsProvider.isHandlerEnabledForCourse( + courseId, this.handlerSchema.restricttoenrolledcourses, this.bootstrapResult.restrict); + } + + /** + * Returns the data needed to render the handler. + * @param {any} user User object. + * @param {number} courseId Course ID where to show. + * @return {CoreUserProfileHandlerData} Data to be shown. + */ + getDisplayData(user: any, courseId: number): CoreUserProfileHandlerData { + return { + title: this.title, + icon: this.handlerSchema.displaydata.icon, + class: this.handlerSchema.displaydata.class, + action: (event: Event, navCtrl: NavController, user: any, courseId?: number): void => { + event.preventDefault(); + event.stopPropagation(); + + navCtrl.push('CoreSiteAddonsAddonPage', { + title: this.title, + component: this.addon.component, + method: this.handlerSchema.method, + args: { + courseid: courseId, + userid: user.id + }, + bootstrapResult: this.bootstrapResult + }); + } + }; + } +} diff --git a/src/core/siteaddons/classes/user-profile-field-handler.ts b/src/core/siteaddons/classes/user-profile-field-handler.ts new file mode 100644 index 000000000..2ab04e807 --- /dev/null +++ b/src/core/siteaddons/classes/user-profile-field-handler.ts @@ -0,0 +1,59 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Injector } from '@angular/core'; +import { CoreUserProfileFieldHandler, CoreUserProfileFieldHandlerData } from '../../user/providers/user-profile-field-delegate'; +import { CoreSiteAddonsBaseHandler } from './base-handler'; +import { CoreSiteAddonsUserProfileFieldComponent } from '../components/user-profile-field/user-profile-field'; + +/** + * Handler to display a site addon in the user profile. + */ +export class CoreSiteAddonsUserProfileFieldHandler extends CoreSiteAddonsBaseHandler implements CoreUserProfileFieldHandler { + + constructor(name: string) { + super(name); + } + + /** + * Return the Component to use to display the user profile field. + * It's recommended to return the class of the component, but you can also return an instance of the component. + * + * @param {Injector} injector Injector. + * @return {any|Promise} The component (or promise resolved with component) to use, undefined if not found. + */ + getComponent(injector: Injector): any | Promise { + return CoreSiteAddonsUserProfileFieldComponent; + } + + /** + * Get the data to send for the field based on the input data. + * @param {any} field User field to get the data for. + * @param {boolean} signup True if user is in signup page. + * @param {string} [registerAuth] Register auth method. E.g. 'email'. + * @param {any} formValues Form Values. + * @return {Promise|CoreUserProfileFieldHandlerData} Data to send for the field. + */ + getData(field: any, signup: boolean, registerAuth: string, formValues: any): + Promise | CoreUserProfileFieldHandlerData { + // No getData function implemented, use a default behaviour. + const name = 'profile_field_' + field.shortname; + + return { + type: field.type || field.datatype, + name: name, + value: formValues[name] + }; + } +} diff --git a/src/core/siteaddons/providers/helper.ts b/src/core/siteaddons/providers/helper.ts index 015afa844..099864fe0 100644 --- a/src/core/siteaddons/providers/helper.ts +++ b/src/core/siteaddons/providers/helper.ts @@ -13,35 +13,32 @@ // limitations under the License. import { Injectable, Injector } from '@angular/core'; -import { NavController, NavOptions } from 'ionic-angular'; import { CoreEventsProvider } from '../../../providers/events'; import { CoreLangProvider } from '../../../providers/lang'; import { CoreLoggerProvider } from '../../../providers/logger'; import { CoreSite } from '../../../classes/site'; import { CoreSitesProvider } from '../../../providers/sites'; import { CoreUtilsProvider } from '../../../providers/utils/utils'; -import { CoreMainMenuDelegate, CoreMainMenuHandler, CoreMainMenuHandlerData } from '../../mainmenu/providers/delegate'; -import { - CoreCourseModuleDelegate, CoreCourseModuleHandler, CoreCourseModuleHandlerData -} from '../../course/providers/module-delegate'; -import { CoreCourseModulePrefetchDelegate } from '../../course/providers/module-prefetch-delegate'; -import { - CoreCourseOptionsDelegate, CoreCourseOptionsHandler, CoreCourseOptionsHandlerData -} from '../../course/providers/options-delegate'; -import { CoreCourseFormatDelegate, CoreCourseFormatHandler } from '../../course/providers/format-delegate'; -import { CoreUserDelegate, CoreUserProfileHandler, CoreUserProfileHandlerData } from '../../user/providers/user-delegate'; -import { - CoreUserProfileFieldDelegate, CoreUserProfileFieldHandler, CoreUserProfileFieldHandlerData -} from '../../user/providers/user-profile-field-delegate'; -import { CoreDelegateHandler } from '../../../classes/delegate'; -import { CoreSiteAddonsModuleIndexComponent } from '../components/module-index/module-index'; -import { CoreSiteAddonsCourseOptionComponent } from '../components/course-option/course-option'; -import { CoreSiteAddonsCourseFormatComponent } from '../components/course-format/course-format'; -import { CoreSiteAddonsUserProfileFieldComponent } from '../components/user-profile-field/user-profile-field'; import { CoreSiteAddonsProvider } from './siteaddons'; -import { CoreSiteAddonsModulePrefetchHandler } from '../classes/module-prefetch-handler'; import { CoreCompileProvider } from '../../compile/providers/compile'; -import { CoreCoursesProvider } from '../../courses/providers/courses'; + +// Delegates +import { CoreMainMenuDelegate } from '../../mainmenu/providers/delegate'; +import { CoreCourseModuleDelegate } from '../../course/providers/module-delegate'; +import { CoreCourseModulePrefetchDelegate } from '../../course/providers/module-prefetch-delegate'; +import { CoreCourseOptionsDelegate } from '../../course/providers/options-delegate'; +import { CoreCourseFormatDelegate } from '../../course/providers/format-delegate'; +import { CoreUserDelegate } from '../../user/providers/user-delegate'; +import { CoreUserProfileFieldDelegate } from '../../user/providers/user-profile-field-delegate'; + +// Handler classes. +import { CoreSiteAddonsCourseFormatHandler } from '../classes/course-format-handler'; +import { CoreSiteAddonsCourseOptionHandler } from '../classes/course-option-handler'; +import { CoreSiteAddonsModuleHandler } from '../classes/module-handler'; +import { CoreSiteAddonsModulePrefetchHandler } from '../classes/module-prefetch-handler'; +import { CoreSiteAddonsMainMenuHandler } from '../classes/main-menu-handler'; +import { CoreSiteAddonsUserProfileHandler } from '../classes/user-handler'; +import { CoreSiteAddonsUserProfileFieldHandler } from '../classes/user-profile-field-handler'; /** * Helper service to provide functionalities regarding site addons. It basically has the features to load and register site @@ -61,8 +58,8 @@ export class CoreSiteAddonsHelperProvider { private mainMenuDelegate: CoreMainMenuDelegate, private moduleDelegate: CoreCourseModuleDelegate, private userDelegate: CoreUserDelegate, private langProvider: CoreLangProvider, private siteAddonsProvider: CoreSiteAddonsProvider, private prefetchDelegate: CoreCourseModulePrefetchDelegate, - private compileProvider: CoreCompileProvider, private utils: CoreUtilsProvider, eventsProvider: CoreEventsProvider, - private coursesProvider: CoreCoursesProvider, private courseOptionsDelegate: CoreCourseOptionsDelegate, + private compileProvider: CoreCompileProvider, private utils: CoreUtilsProvider, + private courseOptionsDelegate: CoreCourseOptionsDelegate, eventsProvider: CoreEventsProvider, private courseFormatDelegate: CoreCourseFormatDelegate, private profileFieldDelegate: CoreUserProfileFieldDelegate) { this.logger = logger.getInstance('CoreSiteAddonsHelperProvider'); @@ -170,21 +167,6 @@ export class CoreSiteAddonsHelperProvider { }); } - /** - * Create a base handler for a site addon. - * - * @param {string} name Name of the handler. - * @return {CoreDelegateHandler} The base handler. - */ - protected getBaseHandler(name: string): CoreDelegateHandler { - return { - name: name, - isEnabled: (): boolean => { - return true; - } - }; - } - /** * Given a handler's unique name, return the prefix to add to its string keys. * @@ -210,54 +192,6 @@ export class CoreSiteAddonsHelperProvider { return this.getHandlerPrefixForStrings(handlerName) + key; } - /** - * Check if a handler is enabled for a certain course. - * - * @param {number} courseId Course ID to check. - * @param {boolean} [restrictEnrolled] If true or undefined, handler is only enabled for courses the user is enrolled in. - * @param {any} [restrict] Users and courses the handler is restricted to. - * @return {boolean | Promise} Whether the handler is enabled. - */ - protected isHandlerEnabledForCourse(courseId: number, restrictEnrolled?: boolean, restrict?: any): boolean | Promise { - if (restrict && restrict.courses && restrict.courses.indexOf(courseId) == -1) { - // Course is not in the list of restricted courses. - return false; - } - - if (restrictEnrolled || typeof restrictEnrolled == 'undefined') { - // Only enabled for courses the user is enrolled to. Check if the user is enrolled in the course. - return this.coursesProvider.getUserCourse(courseId, true).then(() => { - return true; - }).catch(() => { - return false; - }); - } - - return true; - } - - /** - * Check if a handler is enabled for a certain user. - * - * @param {number} userId User ID to check. - * @param {boolean} [restrictCurrent] Whether handler is only enabled for current user. - * @param {any} [restrict] Users and courses the handler is restricted to. - * @return {boolean} Whether the handler is enabled. - */ - protected isHandlerEnabledForUser(userId: number, restrictCurrent?: boolean, restrict?: any): boolean { - if (restrictCurrent && userId != this.sitesProvider.getCurrentSite().getUserId()) { - // Only enabled for current user. - return false; - } - - if (restrict && restrict.users && restrict.users.indexOf(userId) == -1) { - // User is not in the list of restricted users. - return false; - } - - return true; - } - /** * Check if a certain addon is a site addon and it's enabled in a certain site. * @@ -419,30 +353,9 @@ export class CoreSiteAddonsHelperProvider { protected registerCourseFormatHandler(addon: any, handlerName: string, handlerSchema: any, bootstrapResult: any): string { this.logger.debug('Register site addon in course format delegate:', addon, handlerSchema, bootstrapResult); - // Create the base handler. - const formatName = addon.component.replace('format_', ''), - baseHandler = this.getBaseHandler(formatName); - let handler: CoreCourseFormatHandler; - - // Extend the base handler, adding the properties required by the delegate. - handler = Object.assign(baseHandler, { - canViewAllSections: (course: any): boolean => { - return typeof handlerSchema.canviewallsections != 'undefined' ? handlerSchema.canviewallsections : true; - }, - displayEnableDownload: (course: any): boolean => { - return typeof handlerSchema.displayenabledownload != 'undefined' ? handlerSchema.displayenabledownload : true; - }, - displaySectionSelector: (course: any): boolean => { - return typeof handlerSchema.displaysectionselector != 'undefined' ? handlerSchema.displaysectionselector : true; - }, - getCourseFormatComponent: (injector: Injector, course: any): any | Promise => { - if (handlerSchema.method) { - return CoreSiteAddonsCourseFormatComponent; - } - } - }); - - this.courseFormatDelegate.registerHandler(handler); + // Create and register the handler. + const formatName = addon.component.replace('format_', ''); + this.courseFormatDelegate.registerHandler(new CoreSiteAddonsCourseFormatHandler(formatName, handlerSchema)); return formatName; } @@ -466,40 +379,12 @@ export class CoreSiteAddonsHelperProvider { this.logger.debug('Register site addon in course option delegate:', addon, handlerSchema, bootstrapResult); - // Create the base handler. + // Create and register the handler. const uniqueName = this.siteAddonsProvider.getHandlerUniqueName(addon, handlerName), - baseHandler = this.getBaseHandler(uniqueName), - prefixedTitle = this.getHandlerPrefixedString(baseHandler.name, handlerSchema.displaydata.title); - let handler: CoreCourseOptionsHandler; + prefixedTitle = this.getHandlerPrefixedString(uniqueName, handlerSchema.displaydata.title); - // Extend the base handler, adding the properties required by the delegate. - handler = Object.assign(baseHandler, { - priority: handlerSchema.priority, - isEnabledForCourse: (courseId: number, accessData: any, navOptions?: any, admOptions?: any) - : boolean | Promise => { - return this.isHandlerEnabledForCourse(courseId, handlerSchema.restricttoenrolledcourses, bootstrapResult.restrict); - }, - getDisplayData: (injector: Injector, courseId: number): - CoreCourseOptionsHandlerData | Promise => { - return { - title: prefixedTitle, - class: handlerSchema.displaydata.class, - component: CoreSiteAddonsCourseOptionComponent, - componentData: { - handlerUniqueName: uniqueName - } - }; - }, - prefetch: (course: any): Promise => { - const args = { - courseid: course.id, - }; - - return this.siteAddonsProvider.prefetchFunctions(addon.component, args, handlerSchema, course.id, undefined, true); - } - }); - - this.courseOptionsDelegate.registerHandler(handler); + this.courseOptionsDelegate.registerHandler(new CoreSiteAddonsCourseOptionHandler(uniqueName, prefixedTitle, addon, + handlerSchema, bootstrapResult, this.siteAddonsProvider)); return uniqueName; } @@ -523,32 +408,12 @@ export class CoreSiteAddonsHelperProvider { this.logger.debug('Register site addon in main menu delegate:', addon, handlerSchema, bootstrapResult); - // Create the base handler. + // Create and register the handler. const uniqueName = this.siteAddonsProvider.getHandlerUniqueName(addon, handlerName), - baseHandler = this.getBaseHandler(uniqueName), - prefixedTitle = this.getHandlerPrefixedString(baseHandler.name, handlerSchema.displaydata.title); - let mainMenuHandler: CoreMainMenuHandler; + prefixedTitle = this.getHandlerPrefixedString(uniqueName, handlerSchema.displaydata.title); - // Extend the base handler, adding the properties required by the delegate. - mainMenuHandler = Object.assign(baseHandler, { - priority: handlerSchema.priority, - getDisplayData: (): CoreMainMenuHandlerData => { - return { - title: prefixedTitle, - icon: handlerSchema.displaydata.icon, - class: handlerSchema.displaydata.class, - page: 'CoreSiteAddonsAddonPage', - pageParams: { - title: prefixedTitle, - component: addon.component, - method: handlerSchema.method, - bootstrapResult: bootstrapResult - } - }; - } - }); - - this.mainMenuDelegate.registerHandler(mainMenuHandler); + this.mainMenuDelegate.registerHandler( + new CoreSiteAddonsMainMenuHandler(uniqueName, prefixedTitle, addon, handlerSchema, bootstrapResult)); return uniqueName; } @@ -572,46 +437,17 @@ export class CoreSiteAddonsHelperProvider { this.logger.debug('Register site addon in module delegate:', addon, handlerSchema, bootstrapResult); - // Create the base handler. - const modName = addon.component.replace('mod_', ''), - baseHandler = this.getBaseHandler(modName), - hasOfflineFunctions = !!(handlerSchema.offlinefunctions && Object.keys(handlerSchema.offlinefunctions).length), - showDowloadButton = handlerSchema.downloadbutton; - let moduleHandler: CoreCourseModuleHandler; + // Create and register the handler. + const modName = addon.component.replace('mod_', ''); - // Extend the base handler, adding the properties required by the delegate. - moduleHandler = Object.assign(baseHandler, { - getData: (module: any, courseId: number, sectionId: number): CoreCourseModuleHandlerData => { - return { - title: module.name, - icon: handlerSchema.displaydata.icon, - class: handlerSchema.displaydata.class, - showDownloadButton: typeof showDowloadButton != 'undefined' ? showDowloadButton : hasOfflineFunctions, - action: (event: Event, navCtrl: NavController, module: any, courseId: number, options: NavOptions): void => { - event.preventDefault(); - event.stopPropagation(); + this.moduleDelegate.registerHandler(new CoreSiteAddonsModuleHandler(modName, handlerSchema)); - navCtrl.push('CoreSiteAddonsModuleIndexPage', { - title: module.name, - module: module, - courseId: courseId - }, options); - } - }; - }, - getMainComponent: (injector: Injector, course: any, module: any): any | Promise => { - return CoreSiteAddonsModuleIndexComponent; - } - }); - - if (hasOfflineFunctions) { + if (handlerSchema.offlinefunctions && Object.keys(handlerSchema.offlinefunctions).length) { // Register the prefetch handler. this.prefetchDelegate.registerHandler(new CoreSiteAddonsModulePrefetchHandler( this.injector, this.siteAddonsProvider, addon.component, modName, handlerSchema)); } - this.moduleDelegate.registerHandler(moduleHandler); - return modName; } @@ -634,58 +470,12 @@ export class CoreSiteAddonsHelperProvider { this.logger.debug('Register site addon in user profile delegate:', addon, handlerSchema, bootstrapResult); - // Create the base handler. + // Create and register the handler. const uniqueName = this.siteAddonsProvider.getHandlerUniqueName(addon, handlerName), - baseHandler = this.getBaseHandler(uniqueName), - prefixedTitle = this.getHandlerPrefixedString(baseHandler.name, handlerSchema.displaydata.title); - let userHandler: CoreUserProfileHandler, - type = handlerSchema.type; + prefixedTitle = this.getHandlerPrefixedString(uniqueName, handlerSchema.displaydata.title); - // Only support TYPE_COMMUNICATION and TYPE_NEW_PAGE. - if (type != CoreUserDelegate.TYPE_COMMUNICATION) { - type = CoreUserDelegate.TYPE_NEW_PAGE; - } - - // Extend the base handler, adding the properties required by the delegate. - userHandler = Object.assign(baseHandler, { - priority: handlerSchema.priority, - type: type, - isEnabledForUser: (user: any, courseId: number, navOptions?: any, admOptions?: any): boolean | Promise => { - // First check if it's enabled for the user. - const enabledForUser = this.isHandlerEnabledForUser(user.id, handlerSchema.restricttocurrentuser, - bootstrapResult.restrict); - if (!enabledForUser) { - return false; - } - - // Enabled for user, check if it's enabled for the course. - return this.isHandlerEnabledForCourse(courseId, handlerSchema.restricttoenrolledcourses, bootstrapResult.restrict); - }, - getDisplayData: (user: any, courseId: number): CoreUserProfileHandlerData => { - return { - title: prefixedTitle, - icon: handlerSchema.displaydata.icon, - class: handlerSchema.displaydata.class, - action: (event: Event, navCtrl: NavController, user: any, courseId?: number): void => { - event.preventDefault(); - event.stopPropagation(); - - navCtrl.push('CoreSiteAddonsAddonPage', { - title: prefixedTitle, - component: addon.component, - method: handlerSchema.method, - args: { - courseid: courseId, - userid: user.id - }, - bootstrapResult: bootstrapResult - }); - } - }; - } - }); - - this.userDelegate.registerHandler(userHandler); + this.userDelegate.registerHandler(new CoreSiteAddonsUserProfileHandler(uniqueName, prefixedTitle, addon, handlerSchema, + bootstrapResult, this.siteAddonsProvider)); return uniqueName; } @@ -712,37 +502,23 @@ export class CoreSiteAddonsHelperProvider { // Execute the main method and its JS. The template returned will be used in the profile field component. return this.executeMethodAndJS(addon, handlerSchema.method).then((result) => { - // Create the base handler. + // Create and register the handler. const fieldType = addon.component.replace('profilefield_', ''), - baseHandler = this.getBaseHandler(fieldType); - let fieldHandler: CoreUserProfileFieldHandler; + fieldHandler = new CoreSiteAddonsUserProfileFieldHandler(fieldType); // Store in handlerSchema some data required by the component. handlerSchema.methodTemplates = result.templates; handlerSchema.methodJSResult = result.jsResult; - // Extend the base handler, adding the properties required by the delegate. - fieldHandler = Object.assign(baseHandler, { - getData: (field: any, signup: boolean, registerAuth: string, formValues: any): - Promise | CoreUserProfileFieldHandlerData => { - if (result && result.jsResult && result.jsResult.getData) { - // The JS of the main method implements the getData function, use it. - return result.jsResult.getData(); + if (result && result.jsResult) { + // Override default handler functions with the result of the method JS. + for (const property in fieldHandler) { + if (property != 'constructor' && typeof fieldHandler[property] == 'function' && + typeof result.jsResult[property] == 'function') { + fieldHandler[property] = result.jsResult[property].bind(fieldHandler); } - - // No getData function implemented, use a default behaviour. - const name = 'profile_field_' + field.shortname; - - return { - type: field.type || field.datatype, - name: name, - value: formValues[name] - }; - }, - getComponent: (injector: Injector): any | Promise => { - return CoreSiteAddonsUserProfileFieldComponent; } - }); + } this.profileFieldDelegate.registerHandler(fieldHandler); diff --git a/src/core/siteaddons/providers/siteaddons.ts b/src/core/siteaddons/providers/siteaddons.ts index 777973182..6103c3b09 100644 --- a/src/core/siteaddons/providers/siteaddons.ts +++ b/src/core/siteaddons/providers/siteaddons.ts @@ -22,6 +22,7 @@ import { CoreSite, CoreSiteWSPreSets } from '../../../classes/site'; import { CoreSitesProvider } from '../../../providers/sites'; import { CoreUtilsProvider } from '../../../providers/utils/utils'; import { CoreConfigConstants } from '../../../configconstants'; +import { CoreCoursesProvider } from '../../courses/providers/courses'; /** * Handler of a site addon. @@ -64,7 +65,7 @@ export class CoreSiteAddonsProvider { constructor(logger: CoreLoggerProvider, private sitesProvider: CoreSitesProvider, private utils: CoreUtilsProvider, private langProvider: CoreLangProvider, private appProvider: CoreAppProvider, private platform: Platform, - private filepoolProvider: CoreFilepoolProvider) { + private filepoolProvider: CoreFilepoolProvider, private coursesProvider: CoreCoursesProvider) { this.logger = logger.getInstance('CoreUserProvider'); } @@ -338,6 +339,54 @@ export class CoreSiteAddonsProvider { return site.wsAvailable('tool_mobile_get_content'); } + /** + * Check if a handler is enabled for a certain course. + * + * @param {number} courseId Course ID to check. + * @param {boolean} [restrictEnrolled] If true or undefined, handler is only enabled for courses the user is enrolled in. + * @param {any} [restrict] Users and courses the handler is restricted to. + * @return {boolean | Promise} Whether the handler is enabled. + */ + isHandlerEnabledForCourse(courseId: number, restrictEnrolled?: boolean, restrict?: any): boolean | Promise { + if (restrict && restrict.courses && restrict.courses.indexOf(courseId) == -1) { + // Course is not in the list of restricted courses. + return false; + } + + if (restrictEnrolled || typeof restrictEnrolled == 'undefined') { + // Only enabled for courses the user is enrolled to. Check if the user is enrolled in the course. + return this.coursesProvider.getUserCourse(courseId, true).then(() => { + return true; + }).catch(() => { + return false; + }); + } + + return true; + } + + /** + * Check if a handler is enabled for a certain user. + * + * @param {number} userId User ID to check. + * @param {boolean} [restrictCurrent] Whether handler is only enabled for current user. + * @param {any} [restrict] Users and courses the handler is restricted to. + * @return {boolean} Whether the handler is enabled. + */ + isHandlerEnabledForUser(userId: number, restrictCurrent?: boolean, restrict?: any): boolean { + if (restrictCurrent && userId != this.sitesProvider.getCurrentSite().getUserId()) { + // Only enabled for current user. + return false; + } + + if (restrict && restrict.users && restrict.users.indexOf(userId) == -1) { + // User is not in the list of restricted users. + return false; + } + + return true; + } + /** * Load other data into args as determined by useOtherData list. * If useOtherData is undefined, it won't add any data.