// (C) Copyright 2015 Moodle Pty Ltd. // // 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 { ContextLevel } from '@/core/constants'; import { Injectable } from '@angular/core'; import { CoreSites } from '@services/sites'; import { CoreUtils } from '@services/utils/utils'; import { makeSingleton } from '@singletons'; import { CoreRatingDBPrimaryData, CoreRatingDBRecord, RATINGS_TABLE } from './database/rating'; /** * Structure of item sets. */ export interface CoreRatingItemSet { component: string; ratingArea: string; contextLevel: ContextLevel; instanceId: number; itemSetId: number; courseId?: number; } /** * Service to handle offline data for rating. */ @Injectable( { providedIn: 'root' }) export class CoreRatingOfflineProvider { /** * Get an offline rating. * * @param contextLevel Context level: course, module, user, etc. * @param instanceId Context instance id. * @param component Component. Example: "mod_forum". * @param ratingArea Rating area. Example: "post". * @param itemId Item id. Example: forum post id. * @param siteId Site ID. If not defined, current site. * @return Promise resolved with the saved rating, rejected if not found. */ async getRating( contextLevel: ContextLevel, instanceId: number, component: string, ratingArea: string, itemId: number, siteId?: string, ): Promise { const site = await CoreSites.getSite(siteId); const conditions: CoreRatingDBPrimaryData = { contextlevel: contextLevel, instanceid: instanceId, component: component, ratingarea: ratingArea, itemid: itemId, }; return site.getDb().getRecord(RATINGS_TABLE, conditions); } /** * Add an offline rating. * * @param component Component. Example: "mod_forum". * @param ratingArea Rating area. Example: "post". * @param contextLevel Context level: course, module, user, etc. * @param instanceId Context instance id. * @param itemId Item id. Example: forum post id. * @param itemSetId Item set id. Example: forum discussion id. * @param courseId Course id. * @param scaleId Scale id. * @param rating Rating value. Use CoreRatingProvider.UNSET_RATING to delete rating. * @param ratedUserId Rated user id. * @param aggregateMethod Aggregate method. * @param siteId Site ID. If not defined, current site. * @return Promise resolved when the rating is saved. */ async addRating( component: string, ratingArea: string, contextLevel: ContextLevel, instanceId: number, itemId: number, itemSetId: number, courseId: number, scaleId: number, rating: number, ratedUserId: number, aggregateMethod: number, siteId?: string, ): Promise { const site = await CoreSites.getSite(siteId); const data: CoreRatingDBRecord = { component: component, ratingarea: ratingArea, contextlevel: contextLevel, instanceid: instanceId, itemid: itemId, itemsetid: itemSetId, courseid: courseId, scaleid: scaleId, rating: rating, rateduserid: ratedUserId, aggregation: aggregateMethod, }; await site.getDb().insertRecord(RATINGS_TABLE, data); } /** * Delete offline rating. * * @param component Component. Example: "mod_forum". * @param ratingArea Rating area. Example: "post". * @param contextLevel Context level: course, module, user, etc. * @param itemId Item id. Example: forum post id. * @param siteId Site ID. If not defined, current site. * @return Promise resolved when the rating is saved. */ async deleteRating( component: string, ratingArea: string, contextLevel: ContextLevel, instanceId: number, itemId: number, siteId?: string, ): Promise { const site = await CoreSites.getSite(siteId); const conditions: CoreRatingDBPrimaryData = { component: component, ratingarea: ratingArea, contextlevel: contextLevel, instanceid: instanceId, itemid: itemId, }; await site.getDb().deleteRecords(RATINGS_TABLE, conditions); } /** * Get the list of item sets in a component or instance. * * @param component Component. Example: "mod_forum". * @param ratingArea Rating Area. Example: "post". * @param contextLevel Context level: course, module, user, etc. * @param instanceId Context instance id. * @param itemSetId Item set id. * @param siteId Site ID. If not defined, current site. * @return Promise resolved with the list of item set ids. */ async getItemSets( component: string, ratingArea: string, contextLevel?: ContextLevel, instanceId?: number, itemSetId?: number, siteId?: string, ): Promise { const site = await CoreSites.getSite(siteId); const fields = 'DISTINCT contextlevel, instanceid, itemsetid, courseid'; const conditions: Partial = { component, ratingarea: ratingArea, }; if (contextLevel && instanceId) { conditions.contextlevel = contextLevel; conditions.instanceid = instanceId; } if (itemSetId) { conditions.itemsetid = itemSetId; } const records = await site.getDb().getRecords(RATINGS_TABLE, conditions, undefined, fields); return records.map((record) => ({ component, ratingArea, contextLevel: record.contextlevel, instanceId: record.instanceid, itemSetId: record.itemsetid, courseId: record.courseid, })); } /** * Get offline ratings of an item set. * * @param component Component. Example: "mod_forum". * @param ratingArea Rating Area. Example: "post". * @param contextLevel Context level: course, module, user, etc. * @param itemId Item id. Example: forum post id. * @param itemSetId Item set id. Example: forum discussion id. * @param siteId Site ID. If not defined, current site. * @return Promise resolved with the list of ratings. */ async getRatings( component: string, ratingArea: string, contextLevel: ContextLevel, instanceId: number, itemSetId: number, siteId?: string, ): Promise { const site = await CoreSites.getSite(siteId); const conditions: Partial = { component, ratingarea: ratingArea, contextlevel: contextLevel, instanceid: instanceId, itemsetid: itemSetId, }; return site.getDb().getRecords(RATINGS_TABLE, conditions); } /** * Return whether a component, instance or item set has offline ratings. * * @param component Component. Example: "mod_forum". * @param ratingArea Rating Area. Example: "post". * @param contextLevel Context level: course, module, user, etc. * @param instanceId Context instance id. * @param itemSetId Item set id. Example: forum discussion id. * @param siteId Site ID. If not defined, current site. * @return Promise resolved with a boolean. */ async hasRatings( component: string, ratingArea: string, contextLevel?: ContextLevel, instanceId?: number, itemSetId?: number, siteId?: string, ): Promise { const site = await CoreSites.getSite(siteId); const conditions: Partial = { component, ratingarea: ratingArea, }; if (contextLevel && instanceId) { conditions.contextlevel = contextLevel; conditions.instanceid = instanceId; } if (itemSetId) { conditions.itemsetid = itemSetId; } return CoreUtils.promiseWorks(site.getDb().recordExists(RATINGS_TABLE, conditions)); } } export const CoreRatingOffline = makeSingleton(CoreRatingOfflineProvider);