// (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 { CoreSitesProvider } from '@providers/sites'; import { CoreSite } from '@classes/site'; /** * Service that provides some features regarding comments. */ @Injectable() export class CoreCommentsProvider { protected ROOT_CACHE_KEY = 'mmComments:'; static pageSize = null; static pageSizeOK = false; // If true, the pageSize is definitive. If not, it's a temporal value to reduce WS calls. constructor(private sitesProvider: CoreSitesProvider) {} /** * Check if Calendar is disabled in a certain site. * * @param {CoreSite} [site] Site. If not defined, use current site. * @return {boolean} Whether it's disabled. */ areCommentsDisabledInSite(site?: CoreSite): boolean { site = site || this.sitesProvider.getCurrentSite(); return site.isFeatureDisabled('NoDelegate_CoreComments'); } /** * Check if comments are disabled in a certain site. * * @param {string} [siteId] Site Id. If not defined, use current site. * @return {Promise} Promise resolved with true if disabled, rejected or resolved with false otherwise. */ areCommentsDisabled(siteId?: string): Promise { return this.sitesProvider.getSite(siteId).then((site) => { return this.areCommentsDisabledInSite(site); }); } /** * Returns whether WS to add/delete comments are available in site. * * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved with true if available, resolved with false or rejected otherwise. * @since 3.8 */ isAddCommentsAvailable(siteId?: string): Promise { return this.sitesProvider.getSite(siteId).then((site) => { // First check if it's disabled. if (this.areCommentsDisabledInSite(site)) { return false; } return site.wsAvailable('core_comment_add_comments'); }); } /** * Get cache key for get comments data WS calls. * * @param {string} contextLevel Contextlevel system, course, user... * @param {number} instanceId The Instance id of item associated with the context level. * @param {string} component Component name. * @param {number} itemId Associated id. * @param {string} [area=''] String comment area. Default empty. * @return {string} Cache key. */ protected getCommentsCacheKey(contextLevel: string, instanceId: number, component: string, itemId: number, area: string = ''): string { return this.getCommentsPrefixCacheKey(contextLevel, instanceId) + ':' + component + ':' + itemId + ':' + area; } /** * Get cache key for get comments instance data WS calls. * * @param {string} contextLevel Contextlevel system, course, user... * @param {number} instanceId The Instance id of item associated with the context level. * @return {string} Cache key. */ protected getCommentsPrefixCacheKey(contextLevel: string, instanceId: number): string { return this.ROOT_CACHE_KEY + 'comments:' + contextLevel + ':' + instanceId; } /** * Retrieve a list of comments. * * @param {string} contextLevel Contextlevel system, course, user... * @param {number} instanceId The Instance id of item associated with the context level. * @param {string} component Component name. * @param {number} itemId Associated id. * @param {string} [area=''] String comment area. Default empty. * @param {number} [page=0] Page number (0 based). Default 0. * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved with the comments. */ getComments(contextLevel: string, instanceId: number, component: string, itemId: number, area: string = '', page: number = 0, siteId?: string): Promise { return this.sitesProvider.getSite(siteId).then((site) => { const params: any = { contextlevel: contextLevel, instanceid: instanceId, component: component, itemid: itemId, area: area, page: page, }; const preSets = { cacheKey: this.getCommentsCacheKey(contextLevel, instanceId, component, itemId, area), updateFrequency: CoreSite.FREQUENCY_SOMETIMES }; return site.read('core_comment_get_comments', params, preSets).then((response) => { if (response.comments) { return response; } return Promise.reject(null); }); }); } /** * Get comments count number to show ont he comments component. * * @param {string} contextLevel Contextlevel system, course, user... * @param {number} instanceId The Instance id of item associated with the context level. * @param {string} component Component name. * @param {number} itemId Associated id. * @param {string} [area=''] String comment area. Default empty. * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Comments count with plus sign if needed. */ getCommentsCount(contextLevel: string, instanceId: number, component: string, itemId: number, area: string = '', siteId?: string): Promise { siteId = siteId ? siteId : this.sitesProvider.getCurrentSiteId(); // Convenience function to get comments number on a page. const getCommentsPageCount = (page: number): Promise => { return this.getComments(contextLevel, instanceId, component, itemId, area, page, siteId).then((response) => { if (response.comments) { // Update pageSize with the greatest count at the moment. if (response.comments && response.comments.length > CoreCommentsProvider.pageSize) { CoreCommentsProvider.pageSize = response.comments.length; } return response.comments && response.comments.length ? response.comments.length : 0; } return -1; }).catch(() => { return -1; }); }; return getCommentsPageCount(0).then((count) => { if (CoreCommentsProvider.pageSizeOK && count >= CoreCommentsProvider.pageSize) { // Page Size is ok, show + in case it reached the limit. return (CoreCommentsProvider.pageSize - 1) + '+'; } else if (count < 0 || (CoreCommentsProvider.pageSize && count < CoreCommentsProvider.pageSize)) { return count + ''; } // Call to update page size. return getCommentsPageCount(1).then((countMore) => { // Page limit was reached on the previous call. if (countMore > 0) { CoreCommentsProvider.pageSizeOK = true; return (CoreCommentsProvider.pageSize - 1) + '+'; } return count + ''; }); }); } /** * Invalidates comments data. * * @param {string} contextLevel Contextlevel system, course, user... * @param {number} instanceId The Instance id of item associated with the context level. * @param {string} component Component name. * @param {number} itemId Associated id. * @param {string} [area=''] String comment area. Default empty. * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved when the data is invalidated. */ invalidateCommentsData(contextLevel: string, instanceId: number, component: string, itemId: number, area: string = '', siteId?: string): Promise { return this.sitesProvider.getSite(siteId).then((site) => { // This is done with starting with to avoid conflicts with previous keys that were including page. site.invalidateWsCacheForKeyStartingWith(this.getCommentsCacheKey(contextLevel, instanceId, component, itemId, area) + ':'); return site.invalidateWsCacheForKey(this.getCommentsCacheKey(contextLevel, instanceId, component, itemId, area)); }); } /** * Invalidates all comments data for an instance. * * @param {string} contextLevel Contextlevel system, course, user... * @param {number} instanceId The Instance id of item associated with the context level. * @param {string} [siteId] Site ID. If not defined, current site. * @return {Promise} Promise resolved when the data is invalidated. */ invalidateCommentsByInstance(contextLevel: string, instanceId: number, siteId?: string): Promise { return this.sitesProvider.getSite(siteId).then((site) => { return site.invalidateWsCacheForKeyStartingWith(this.getCommentsPrefixCacheKey(contextLevel, instanceId)); }); } }