From 13f7e61c1c2a45c4d0efc64c7499add0f703b489 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Wed, 15 Nov 2017 08:47:28 +0100 Subject: [PATCH] MOBILE-2261 groups: Implement groups provider --- src/app/app.module.ts | 2 + src/providers/groups.ts | 344 ++++++++++++++++++++++++++++++++++++++++ src/providers/sites.ts | 12 ++ 3 files changed, 358 insertions(+) create mode 100644 src/providers/groups.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 52cade374..c57caa521 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -44,6 +44,7 @@ import { CoreEventsProvider } from '../providers/events'; import { CoreSitesFactoryProvider } from '../providers/sites-factory'; import { CoreSitesProvider } from '../providers/sites'; import { CoreLocalNotificationsProvider } from '../providers/local-notifications'; +import { CoreGroupsProvider } from '../providers/groups'; // For translate loader. AoT requires an exported function for factories. export function createTranslateLoader(http: HttpClient) { @@ -95,6 +96,7 @@ export function createTranslateLoader(http: HttpClient) { CoreSitesFactoryProvider, CoreSitesProvider, CoreLocalNotificationsProvider, + CoreGroupsProvider, ] }) export class AppModule { diff --git a/src/providers/groups.ts b/src/providers/groups.ts new file mode 100644 index 000000000..437fe5288 --- /dev/null +++ b/src/providers/groups.ts @@ -0,0 +1,344 @@ +// (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 { Injectable } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; +import { CoreSitesProvider } from './sites'; + +export interface CoreGroupInfo { + groups?: any[]; // List of groups. + separateGroups?: boolean; // Whether it's separate groups. + visibleGroups?: boolean; // Whether it's visible groups. +}; + +/* + * Service to handle groups. +*/ +@Injectable() +export class CoreGroupsProvider { + // Group mode constants. + public static NOGROUPS = 0; + public static SEPARATEGROUPS = 1; + public static VISIBLEGROUPS = 2; + + constructor(private sitesProvider: CoreSitesProvider, private translate: TranslateService) {} + + /** + * Check if group mode of an activity is enabled. + * + * @param {number} cmId Course module ID. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved with true if the activity has groups, resolved with false otherwise. + */ + activityHasGroups(cmId: number, siteId?: string) : Promise { + return this.getActivityGroupMode(cmId, siteId).then((groupmode) => { + return groupmode === CoreGroupsProvider.SEPARATEGROUPS || groupmode === CoreGroupsProvider.VISIBLEGROUPS; + }).catch(() => { + return false; + }); + } + + /** + * Check if current site allows getting activity group mode. + * + * @return {boolean} Whether it can get activity group mode. + */ + canGetActivityGroupMode() : boolean { + return this.sitesProvider.getCurrentSite().wsAvailable('core_group_get_activity_groupmode'); + } + + /** + * Get the groups allowed in an activity. + * + * @param {number} cmId Course module ID. + * @param {number} [userId] User ID. If not defined, use current user. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved when the groups are retrieved. + */ + getActivityAllowedGroups(cmId: number, userId?: number, siteId?: string) : Promise { + return this.sitesProvider.getSite(siteId).then((site) => { + userId = userId || site.getUserId(); + + const params = { + cmid: cmId, + userid: userId + }, + preSets = { + cacheKey: this.getActivityAllowedGroupsCacheKey(cmId, userId) + } + + return site.read('core_group_get_activity_allowed_groups', params, preSets).then((response) => { + if (!response || !response.groups) { + return Promise.reject(null); + } + return response.groups; + }); + }); + } + + /** + * Get cache key for group mode WS calls. + * + * @param {number} cmId Course module ID. + * @param {number} userId User ID. + * @return {string} Cache key. + */ + protected getActivityAllowedGroupsCacheKey(cmId: number, userId: number) : string { + return this.getRootCacheKey() + 'allowedgroups:' + cmId + ':' + userId; + } + + /** + * Get the groups allowed in an activity if they are allowed. + * + * @param {number} cmId Course module ID. + * @param {number} [userId] User ID. If not defined, use current user. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved when the groups are retrieved. If not allowed, empty array will be returned. + */ + getActivityAllowedGroupsIfEnabled(cmId: number, userId?: number, siteId?: string) : Promise { + siteId = siteId || this.sitesProvider.getCurrentSiteId(); + + // Get real groupmode, in case it's forced by the course. + return this.activityHasGroups(cmId, siteId).then((hasGroups) => { + if (hasGroups) { + // Get the groups available for the user. + return this.getActivityAllowedGroups(cmId, userId, siteId); + } + return []; + }); + } + + /** + * Helper function to get activity group info (group mode and list of groups). + * + * @param {number} cmId Course module ID. + * @param {boolean} [addAllParts=true] Whether to add the all participants option. Always true for visible groups. + * @param {number} [userId] User ID. If not defined, use current user. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved with the group info. + */ + getActivityGroupInfo(cmId: number, addAllParts = true, userId?: number, siteId?: string) : Promise { + let groupInfo: CoreGroupInfo = { + groups: [] + } + + return this.getActivityGroupMode(cmId, siteId).then((groupMode) => { + groupInfo.separateGroups = groupMode === CoreGroupsProvider.SEPARATEGROUPS; + groupInfo.visibleGroups = groupMode === CoreGroupsProvider.VISIBLEGROUPS; + + if (groupInfo.separateGroups || groupInfo.visibleGroups) { + return this.getActivityAllowedGroups(cmId, userId, siteId); + } + return []; + }).then((groups) => { + if (groups.length <= 0) { + groupInfo.separateGroups = false; + groupInfo.visibleGroups = false; + } else { + if (addAllParts || groupInfo.visibleGroups) { + groupInfo.groups.push({id: 0, name: this.translate.instant('mm.core.allparticipants')}); + } + groupInfo.groups = groupInfo.groups.concat(groups); + } + return groupInfo; + }); + } + + /** + * Get the group mode of an activity. + * + * @param {number} cmId Course module ID. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved when the group mode is retrieved. + */ + getActivityGroupMode(cmId: number, siteId?: string) : Promise { + return this.sitesProvider.getSite(siteId).then((site) => { + const params = { + cmid: cmId + }, + preSets = { + cacheKey: this.getActivityGroupModeCacheKey(cmId) + } + + return site.read('core_group_get_activity_groupmode', params, preSets).then((response) => { + if (!response || typeof response.groupmode == 'undefined') { + return Promise.reject(null); + } + return response.groupmode; + }); + }); + } + + /** + * Get cache key for group mode WS calls. + * + * @param {number} cmId Course module ID. + * @return {string} Cache key. + */ + protected getActivityGroupModeCacheKey(cmId: number) : string { + return this.getRootCacheKey() + 'groupmode:' + cmId; + } + + /** + * Get the "root" cache key for WS calls. + * + * @return {string} Cache key. + */ + protected getRootCacheKey() : string { + return 'mmGroups:'; + } + + /** + * Get user groups in all the supplied courses. + * + * @param {any[]} courses List of courses or course ids to get the groups from. + * @param {string} [siteId] Site to get the groups from. If not defined, use current site. + * @param {number} [userId] ID of the user. If not defined, use the userId related to siteId. + * @return {Promise} Promise resolved when the groups are retrieved. + */ + getUserGroups(courses: any[], siteId?: string, userId?: number) : Promise { + let promises = [], + groups = []; + + courses.forEach((course) => { + const courseId = typeof course == 'object' ? course.id : course; + promises.push(this.getUserGroupsInCourse(courseId, siteId, userId).then((courseGroups) => { + groups = groups.concat(courseGroups); + })); + }); + + return Promise.all(promises).then(() => { + return groups; + }); + } + + /** + * Get user groups in a course. + * + * @param {number} courseId ID of the course. + * @param {string} [siteId] Site to get the groups from. If not defined, use current site. + * @param {number} [userId] ID of the user. If not defined, use ID related to siteid. + * @return {Promise} Promise resolved when the groups are retrieved. + */ + getUserGroupsInCourse(courseId: number, siteId?: string, userId?: number) : Promise { + return this.sitesProvider.getSite(siteId).then((site) => { + let data = { + userid: userId || site.getUserId(), + courseid: courseId + }, preSets = { + cacheKey: this.getUserGroupsInCourseCacheKey(courseId, userId) + }; + + return site.read('core_group_get_course_user_groups', data, preSets).then((response) => { + if (response && response.groups) { + return response.groups; + } else { + return Promise.reject(null); + } + }); + }); + } + + /** + * Get cache key for user groups in course WS calls. + * + * @param {number} courseId Course ID. + * @param {number} userId User ID. + * @return {string} Cache key. + */ + protected getUserGroupsInCourseCacheKey(courseId: number, userId: number) : string { + return this.getRootCacheKey() + 'courseGroups:' + courseId + ':' + userId; + } + + /** + * Invalidates activity allowed groups. + * + * @param {number} cmId Course module ID. + * @param {number} [userId] User ID. If not defined, use current user. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved when the data is invalidated. + */ + invalidateActivityAllowedGroups(cmId: number, userId?: number, siteId?: string) : Promise { + return this.sitesProvider.getSite(siteId).then((site) => { + userId = userId || site.getUserId(); + return site.invalidateWsCacheForKey(this.getActivityAllowedGroupsCacheKey(cmId, userId)); + }); + } + + /** + * Invalidates activity group mode. + * + * @param {number} cmId Course module ID. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved when the data is invalidated. + */ + invalidateActivityGroupMode(cmId: number, siteId?: string) : Promise { + return this.sitesProvider.getSite(siteId).then((site) => { + return site.invalidateWsCacheForKey(this.getActivityGroupModeCacheKey(cmId)); + }); + } + + /** + * Invalidates all activity group info: mode and allowed groups. + * + * @param {number} cmId Course module ID. + * @param {number} [userId] User ID. If not defined, use current user. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved when the data is invalidated. + */ + invalidateActivityGroupInfo(cmId: number, userId?: number, siteId?: string) : Promise { + let promises = []; + promises.push(this.invalidateActivityAllowedGroups(cmId, userId, siteId)); + promises.push(this.invalidateActivityGroupMode(cmId, siteId)); + return Promise.all(promises); + } + + /** + * Invalidates user groups in courses. + * + * @param {any[]} courses List of courses or course ids. + * @param {string} [siteId] Site ID. If not defined, current site. + * @param {number} [userId] User ID. If not defined, use current user. + * @return {Promise} Promise resolved when the data is invalidated. + */ + invalidateUserGroups(courses: any[], siteId?: string, userId?: number) : Promise { + return this.sitesProvider.getSite(siteId).then((site) => { + let promises = []; + + userId = userId || site.getUserId(); + + courses.forEach((course) => { + const courseId = typeof course == 'object' ? course.id : course; + promises.push(this.invalidateUserGroupsInCourse(courseId, site.id, userId)); + }); + + return Promise.all(promises); + }); + } + + /** + * Invalidates user groups in course. + * + * @param {number} courseId Course ID. + * @param {string} [siteId] Site ID. If not defined, current site. + * @param {number} [userId] User ID. If not defined, use current user. + * @return {Promise} Promise resolved when the data is invalidated. + */ + invalidateUserGroupsInCourse(courseId: number, siteId?: string, userId?: number) : Promise { + return this.sitesProvider.getSite(siteId).then((site) => { + userId = userId || site.getUserId(); + return site.invalidateWsCacheForKey(this.getUserGroupsInCourseCacheKey(courseId, userId)); + }); + } +} diff --git a/src/providers/sites.ts b/src/providers/sites.ts index cc09aa3e0..7aaea0dc0 100644 --- a/src/providers/sites.ts +++ b/src/providers/sites.ts @@ -557,6 +557,18 @@ export class CoreSitesProvider { return this.currentSite; } + /** + * Get current site ID. + * + * @return {string} Current site ID. + */ + getCurrentSiteId() : string { + if (this.currentSite) { + return this.currentSite.getId(); + } else { + return ''; + } + } /** * Check if the user is logged in a site.