2019-09-26 12:43:29 +02:00
|
|
|
// (C) Copyright 2015 Moodle Pty Ltd.
|
2018-05-14 10:18:21 +02:00
|
|
|
//
|
|
|
|
// 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';
|
2019-05-07 11:30:56 +02:00
|
|
|
import { CoreSite, CoreSiteWSPreSets } from '@classes/site';
|
2018-05-14 10:18:21 +02:00
|
|
|
import { CoreAppProvider } from '@providers/app';
|
|
|
|
import { CoreFilepoolProvider } from '@providers/filepool';
|
|
|
|
import { CoreGroupsProvider } from '@providers/groups';
|
|
|
|
import { CoreSitesProvider } from '@providers/sites';
|
|
|
|
import { CoreUserProvider } from '@core/user/providers/user';
|
|
|
|
import { CoreUtilsProvider } from '@providers/utils/utils';
|
2019-02-04 12:06:05 +01:00
|
|
|
import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper';
|
2018-05-14 10:18:21 +02:00
|
|
|
import { AddonModForumOfflineProvider } from './offline';
|
2019-02-28 17:34:45 +01:00
|
|
|
import { CoreRatingInfo } from '@core/rating/providers/rating';
|
2018-05-14 10:18:21 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Service that provides some features for forums.
|
|
|
|
*/
|
|
|
|
@Injectable()
|
|
|
|
export class AddonModForumProvider {
|
|
|
|
static COMPONENT = 'mmaModForum';
|
|
|
|
static DISCUSSIONS_PER_PAGE = 10; // Max of discussions per page.
|
|
|
|
static NEW_DISCUSSION_EVENT = 'addon_mod_forum_new_discussion';
|
|
|
|
static REPLY_DISCUSSION_EVENT = 'addon_mod_forum_reply_discussion';
|
|
|
|
static VIEW_DISCUSSION_EVENT = 'addon_mod_forum_view_discussion';
|
2019-04-16 16:55:33 +02:00
|
|
|
static CHANGE_DISCUSSION_EVENT = 'addon_mod_forum_lock_discussion';
|
2018-08-16 12:20:23 +02:00
|
|
|
static MARK_READ_EVENT = 'addon_mod_forum_mark_read';
|
2018-05-14 10:18:21 +02:00
|
|
|
|
2019-05-07 11:30:56 +02:00
|
|
|
static PREFERENCE_SORTORDER = 'forum_discussionlistsortorder';
|
|
|
|
static SORTORDER_LASTPOST_DESC = 1;
|
|
|
|
static SORTORDER_LASTPOST_ASC = 2;
|
|
|
|
static SORTORDER_CREATED_DESC = 3;
|
|
|
|
static SORTORDER_CREATED_ASC = 4;
|
|
|
|
static SORTORDER_REPLIES_DESC = 5;
|
|
|
|
static SORTORDER_REPLIES_ASC = 6;
|
|
|
|
|
2019-05-16 15:04:45 +02:00
|
|
|
static ALL_PARTICIPANTS = -1;
|
|
|
|
static ALL_GROUPS = -2;
|
|
|
|
|
2018-05-14 10:18:21 +02:00
|
|
|
protected ROOT_CACHE_KEY = 'mmaModForum:';
|
|
|
|
|
|
|
|
constructor(private appProvider: CoreAppProvider,
|
|
|
|
private sitesProvider: CoreSitesProvider,
|
|
|
|
private groupsProvider: CoreGroupsProvider,
|
|
|
|
private filepoolProvider: CoreFilepoolProvider,
|
|
|
|
private userProvider: CoreUserProvider,
|
|
|
|
private translate: TranslateService,
|
|
|
|
private utils: CoreUtilsProvider,
|
2019-02-04 12:06:05 +01:00
|
|
|
private forumOffline: AddonModForumOfflineProvider,
|
|
|
|
private logHelper: CoreCourseLogHelperProvider) {}
|
2018-05-14 10:18:21 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Get cache key for can add discussion WS calls.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param forumId Forum ID.
|
|
|
|
* @param groupId Group ID.
|
|
|
|
* @return Cache key.
|
2018-05-14 10:18:21 +02:00
|
|
|
*/
|
|
|
|
protected getCanAddDiscussionCacheKey(forumId: number, groupId: number): string {
|
2019-05-07 13:09:55 +02:00
|
|
|
return this.getCommonCanAddDiscussionCacheKey(forumId) + groupId;
|
2018-05-14 10:18:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get common part of cache key for can add discussion WS calls.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param forumId Forum ID.
|
|
|
|
* @return Cache key.
|
2018-05-14 10:18:21 +02:00
|
|
|
*/
|
|
|
|
protected getCommonCanAddDiscussionCacheKey(forumId: number): string {
|
2019-05-07 13:09:55 +02:00
|
|
|
return this.ROOT_CACHE_KEY + 'canadddiscussion:' + forumId + ':';
|
2018-05-14 10:18:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get cache key for forum data WS calls.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param courseId Course ID.
|
|
|
|
* @return Cache key.
|
2018-05-14 10:18:21 +02:00
|
|
|
*/
|
|
|
|
protected getForumDataCacheKey(courseId: number): string {
|
|
|
|
return this.ROOT_CACHE_KEY + 'forum:' + courseId;
|
|
|
|
}
|
|
|
|
|
2019-04-09 15:35:24 +02:00
|
|
|
/**
|
|
|
|
* Get cache key for forum access information WS calls.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param forumId Forum ID.
|
|
|
|
* @return Cache key.
|
2019-04-09 15:35:24 +02:00
|
|
|
*/
|
|
|
|
protected getAccessInformationCacheKey(forumId: number): string {
|
|
|
|
return this.ROOT_CACHE_KEY + 'accessInformation:' + forumId;
|
|
|
|
}
|
|
|
|
|
2018-05-14 10:18:21 +02:00
|
|
|
/**
|
|
|
|
* Get cache key for forum discussion posts WS calls.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param discussionId Discussion ID.
|
|
|
|
* @return Cache key.
|
2018-05-14 10:18:21 +02:00
|
|
|
*/
|
|
|
|
protected getDiscussionPostsCacheKey(discussionId: number): string {
|
|
|
|
return this.ROOT_CACHE_KEY + 'discussion:' + discussionId;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get cache key for forum discussions list WS calls.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param forumId Forum ID.
|
|
|
|
* @param sortOrder Sort order.
|
|
|
|
* @return Cache key.
|
2018-05-14 10:18:21 +02:00
|
|
|
*/
|
2019-05-07 11:30:56 +02:00
|
|
|
protected getDiscussionsListCacheKey(forumId: number, sortOrder: number): string {
|
|
|
|
let key = this.ROOT_CACHE_KEY + 'discussions:' + forumId;
|
|
|
|
|
|
|
|
if (sortOrder != AddonModForumProvider.SORTORDER_LASTPOST_DESC) {
|
|
|
|
key += ':' + sortOrder;
|
|
|
|
}
|
|
|
|
|
|
|
|
return key;
|
2018-05-14 10:18:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add a new discussion. It will fail if offline or cannot connect.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param forumId Forum ID.
|
|
|
|
* @param subject New discussion's subject.
|
|
|
|
* @param message New discussion's message.
|
|
|
|
* @param options Options (subscribe, pin, ...).
|
|
|
|
* @param groupId Group this discussion belongs to.
|
|
|
|
* @param siteId Site ID. If not defined, current site.
|
|
|
|
* @return Promise resolved when the discussion is created.
|
2018-05-14 10:18:21 +02:00
|
|
|
*/
|
|
|
|
addNewDiscussionOnline(forumId: number, subject: string, message: string, options?: any, groupId?: number, siteId?: string)
|
|
|
|
: Promise<any> {
|
|
|
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
|
|
|
const params: any = {
|
|
|
|
forumid: forumId,
|
|
|
|
subject: subject,
|
|
|
|
message: message,
|
|
|
|
options: this.utils.objectToArrayOfObjects(options, 'name', 'value')
|
|
|
|
};
|
|
|
|
|
|
|
|
if (groupId) {
|
|
|
|
params.groupid = groupId;
|
|
|
|
}
|
|
|
|
|
|
|
|
return site.write('mod_forum_add_discussion', params).then((response) => {
|
|
|
|
// Other errors ocurring.
|
|
|
|
if (!response || !response.discussionid) {
|
2018-05-30 11:32:54 +02:00
|
|
|
return Promise.reject(this.utils.createFakeWSError(''));
|
2018-05-14 10:18:21 +02:00
|
|
|
} else {
|
|
|
|
return response.discussionid;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if a user can post to a certain group.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param forumId Forum ID.
|
|
|
|
* @param groupId Group ID.
|
|
|
|
* @param siteId Site ID. If not defined, current site.
|
|
|
|
* @return Promise resolved with an object with the following properties:
|
|
|
|
* - status (boolean)
|
|
|
|
* - canpindiscussions (boolean)
|
|
|
|
* - cancreateattachment (boolean)
|
2018-05-14 10:18:21 +02:00
|
|
|
*/
|
2018-05-16 16:10:14 +02:00
|
|
|
canAddDiscussion(forumId: number, groupId: number, siteId?: string): Promise<any> {
|
2018-05-14 10:18:21 +02:00
|
|
|
const params = {
|
|
|
|
forumid: forumId,
|
|
|
|
groupid: groupId
|
|
|
|
};
|
|
|
|
const preSets = {
|
|
|
|
cacheKey: this.getCanAddDiscussionCacheKey(forumId, groupId)
|
|
|
|
};
|
|
|
|
|
2018-05-16 16:10:14 +02:00
|
|
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
|
|
|
return site.read('mod_forum_can_add_discussion', params, preSets).then((result) => {
|
|
|
|
if (result) {
|
|
|
|
if (typeof result.canpindiscussions == 'undefined') {
|
|
|
|
// WS doesn't support it yet, default it to false to prevent students from seing the option.
|
|
|
|
result.canpindiscussions = false;
|
|
|
|
}
|
|
|
|
if (typeof result.cancreateattachment == 'undefined') {
|
|
|
|
// WS doesn't support it yet, default it to true since usually the users will be able to create them.
|
|
|
|
result.cancreateattachment = true;
|
|
|
|
}
|
2018-05-14 10:18:21 +02:00
|
|
|
|
2018-05-16 16:10:14 +02:00
|
|
|
return result;
|
|
|
|
}
|
2018-05-14 10:18:21 +02:00
|
|
|
|
2018-05-16 16:10:14 +02:00
|
|
|
return Promise.reject(null);
|
|
|
|
});
|
2018-05-14 10:18:21 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if a user can post to all groups.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param forumId Forum ID.
|
|
|
|
* @return Promise resolved with an object with the following properties:
|
|
|
|
* - status (boolean)
|
|
|
|
* - canpindiscussions (boolean)
|
|
|
|
* - cancreateattachment (boolean)
|
2018-05-14 10:18:21 +02:00
|
|
|
*/
|
|
|
|
canAddDiscussionToAll(forumId: number): Promise<any> {
|
2019-05-16 15:04:45 +02:00
|
|
|
return this.canAddDiscussion(forumId, AddonModForumProvider.ALL_PARTICIPANTS);
|
2018-05-14 10:18:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Extract the starting post of a discussion from a list of posts. The post is removed from the array passed as a parameter.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param posts Posts to search.
|
|
|
|
* @return Starting post or undefined if not found.
|
2018-05-14 10:18:21 +02:00
|
|
|
*/
|
|
|
|
extractStartingPost(posts: any[]): any {
|
|
|
|
// Check the last post first, since they'll usually be ordered by create time.
|
|
|
|
for (let i = posts.length - 1; i >= 0; i--) {
|
|
|
|
if (posts[i].parent == 0) {
|
|
|
|
return posts.splice(i, 1).pop(); // Remove it from the array.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* There was a bug adding new discussions to All Participants (see MDL-57962). Check if it's fixed.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @return True if fixed, false otherwise.
|
2018-05-14 10:18:21 +02:00
|
|
|
*/
|
|
|
|
isAllParticipantsFixed(): boolean {
|
|
|
|
return this.sitesProvider.getCurrentSite().isVersionGreaterEqualThan(['3.1.5', '3.2.2']);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Format discussions, setting groupname if the discussion group is valid.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param cmId Forum cmid.
|
|
|
|
* @param discussions List of discussions to format.
|
|
|
|
* @return Promise resolved with the formatted discussions.
|
2018-05-14 10:18:21 +02:00
|
|
|
*/
|
|
|
|
formatDiscussionsGroups(cmId: number, discussions: any[]): Promise<any[]> {
|
|
|
|
discussions = this.utils.clone(discussions);
|
|
|
|
|
2019-07-26 09:14:19 +02:00
|
|
|
return this.groupsProvider.getActivityAllowedGroups(cmId).then((result) => {
|
2018-05-14 10:18:21 +02:00
|
|
|
const strAllParts = this.translate.instant('core.allparticipants');
|
2019-05-16 15:04:45 +02:00
|
|
|
const strAllGroups = this.translate.instant('core.allgroups');
|
2018-05-14 10:18:21 +02:00
|
|
|
|
|
|
|
// Turn groups into an object where each group is identified by id.
|
|
|
|
const groups = {};
|
2019-07-26 09:14:19 +02:00
|
|
|
result.groups.forEach((fg) => {
|
2018-05-14 10:18:21 +02:00
|
|
|
groups[fg.id] = fg;
|
|
|
|
});
|
|
|
|
|
|
|
|
// Format discussions.
|
|
|
|
discussions.forEach((disc) => {
|
2019-05-16 15:04:45 +02:00
|
|
|
if (disc.groupid == AddonModForumProvider.ALL_PARTICIPANTS) {
|
2018-05-14 10:18:21 +02:00
|
|
|
disc.groupname = strAllParts;
|
2019-05-16 15:04:45 +02:00
|
|
|
} else if (disc.groupid == AddonModForumProvider.ALL_GROUPS) {
|
|
|
|
// Offline discussions only.
|
|
|
|
disc.groupname = strAllGroups;
|
2018-05-14 10:18:21 +02:00
|
|
|
} else {
|
|
|
|
const group = groups[disc.groupid];
|
|
|
|
if (group) {
|
|
|
|
disc.groupname = group.name;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return discussions;
|
|
|
|
}).catch(() => {
|
|
|
|
return discussions;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get all course forums.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param courseId Course ID.
|
|
|
|
* @param siteId Site ID. If not defined, current site.
|
|
|
|
* @return Promise resolved when the forums are retrieved.
|
2018-05-14 10:18:21 +02:00
|
|
|
*/
|
|
|
|
getCourseForums(courseId: number, siteId?: string): Promise<any[]> {
|
|
|
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
|
|
|
const params = {
|
|
|
|
courseids: [courseId]
|
|
|
|
};
|
|
|
|
const preSets = {
|
2019-05-20 12:20:46 +02:00
|
|
|
cacheKey: this.getForumDataCacheKey(courseId),
|
|
|
|
updateFrequency: CoreSite.FREQUENCY_RARELY
|
2018-05-14 10:18:21 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
return site.read('mod_forum_get_forums_by_courses', params, preSets);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get a forum by course module ID.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param courseId Course ID.
|
|
|
|
* @param cmId Course module ID.
|
|
|
|
* @param siteId Site ID. If not defined, current site.
|
|
|
|
* @return Promise resolved when the forum is retrieved.
|
2018-05-14 10:18:21 +02:00
|
|
|
*/
|
|
|
|
getForum(courseId: number, cmId: number, siteId?: string): Promise<any> {
|
|
|
|
return this.getCourseForums(courseId, siteId).then((forums) => {
|
|
|
|
const forum = forums.find((forum) => forum.cmid == cmId);
|
|
|
|
if (forum) {
|
|
|
|
return forum;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Promise.reject(null);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get a forum by forum ID.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param courseId Course ID.
|
|
|
|
* @param forumId Forum ID.
|
|
|
|
* @param siteId Site ID. If not defined, current site.
|
|
|
|
* @return Promise resolved when the forum is retrieved.
|
2018-05-14 10:18:21 +02:00
|
|
|
*/
|
|
|
|
getForumById(courseId: number, forumId: number, siteId?: string): Promise<any> {
|
|
|
|
return this.getCourseForums(courseId, siteId).then((forums) => {
|
|
|
|
const forum = forums.find((forum) => forum.id == forumId);
|
|
|
|
if (forum) {
|
|
|
|
return forum;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Promise.reject(null);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-04-09 15:35:24 +02:00
|
|
|
/**
|
|
|
|
* Get access information for a given forum.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param forumId Forum ID.
|
|
|
|
* @param forceCache True to always get the value from cache. false otherwise.
|
|
|
|
* @param siteId Site ID. If not defined, current site.
|
|
|
|
* @return Object with access information.
|
2019-04-09 15:35:24 +02:00
|
|
|
* @since 3.7
|
|
|
|
*/
|
|
|
|
getAccessInformation(forumId: number, forceCache?: boolean, siteId?: string): Promise<any> {
|
|
|
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
|
|
|
if (!site.wsAvailable('mod_forum_get_forum_access_information')) {
|
|
|
|
// Access information not available for 3.6 or older sites.
|
|
|
|
return Promise.resolve({});
|
|
|
|
}
|
|
|
|
|
|
|
|
const params = {
|
|
|
|
forumid: forumId
|
|
|
|
};
|
|
|
|
const preSets = {
|
|
|
|
cacheKey: this.getAccessInformationCacheKey(forumId),
|
|
|
|
omitExpires: forceCache
|
|
|
|
};
|
|
|
|
|
|
|
|
return site.read('mod_forum_get_forum_access_information', params, preSets);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-05-14 10:18:21 +02:00
|
|
|
/**
|
|
|
|
* Get forum discussion posts.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param discussionId Discussion ID.
|
|
|
|
* @param siteId Site ID. If not defined, current site.
|
|
|
|
* @return Promise resolved with forum posts and rating info.
|
2018-05-14 10:18:21 +02:00
|
|
|
*/
|
2019-02-28 17:34:45 +01:00
|
|
|
getDiscussionPosts(discussionId: number, siteId?: string): Promise<{posts: any[], ratinginfo?: CoreRatingInfo}> {
|
2018-05-14 10:18:21 +02:00
|
|
|
const params = {
|
2018-05-16 16:10:14 +02:00
|
|
|
discussionid: discussionId
|
2018-05-14 10:18:21 +02:00
|
|
|
};
|
|
|
|
const preSets = {
|
2018-05-16 16:10:14 +02:00
|
|
|
cacheKey: this.getDiscussionPostsCacheKey(discussionId)
|
2018-05-14 10:18:21 +02:00
|
|
|
};
|
|
|
|
|
2018-05-16 16:10:14 +02:00
|
|
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
|
|
|
return site.read('mod_forum_get_forum_discussion_posts', params, preSets).then((response) => {
|
|
|
|
if (response) {
|
|
|
|
this.storeUserData(response.posts);
|
2018-05-14 10:18:21 +02:00
|
|
|
|
2019-02-28 17:34:45 +01:00
|
|
|
return response;
|
2018-05-16 16:10:14 +02:00
|
|
|
} else {
|
|
|
|
return Promise.reject(null);
|
|
|
|
}
|
|
|
|
});
|
2018-05-14 10:18:21 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sort forum discussion posts by an specified field.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param posts Discussion posts to be sorted in place.
|
|
|
|
* @param direction Direction of the sorting (ASC / DESC).
|
2018-05-14 10:18:21 +02:00
|
|
|
*/
|
|
|
|
sortDiscussionPosts(posts: any[], direction: string): void {
|
|
|
|
// @todo: Check children when sorting.
|
|
|
|
posts.sort((a, b) => {
|
|
|
|
a = parseInt(a.created, 10);
|
|
|
|
b = parseInt(b.created, 10);
|
|
|
|
if (direction == 'ASC') {
|
|
|
|
return a - b;
|
|
|
|
} else {
|
|
|
|
return b - a;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-05-07 11:30:56 +02:00
|
|
|
/**
|
|
|
|
* Return whether discussion lists can be sorted.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param site Site. If not defined, current site.
|
|
|
|
* @return True if discussion lists can be sorted.
|
2019-05-07 11:30:56 +02:00
|
|
|
*/
|
|
|
|
isDiscussionListSortingAvailable(site?: CoreSite): boolean {
|
|
|
|
site = site || this.sitesProvider.getCurrentSite();
|
|
|
|
|
|
|
|
return site.isVersionGreaterEqualThan('3.7');
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the list of available sort orders.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @return List of sort orders.
|
2019-05-07 11:30:56 +02:00
|
|
|
*/
|
|
|
|
getAvailableSortOrders(): {label: string, value: number}[] {
|
|
|
|
const sortOrders = [
|
|
|
|
{
|
2019-05-16 09:52:08 +02:00
|
|
|
label: 'addon.mod_forum.discussionlistsortbylastpostdesc',
|
2019-05-07 11:30:56 +02:00
|
|
|
value: AddonModForumProvider.SORTORDER_LASTPOST_DESC
|
|
|
|
},
|
|
|
|
];
|
|
|
|
|
|
|
|
if (this.isDiscussionListSortingAvailable()) {
|
|
|
|
sortOrders.push(
|
|
|
|
{
|
2019-05-16 09:52:08 +02:00
|
|
|
label: 'addon.mod_forum.discussionlistsortbylastpostasc',
|
2019-05-07 11:30:56 +02:00
|
|
|
value: AddonModForumProvider.SORTORDER_LASTPOST_ASC
|
|
|
|
},
|
|
|
|
{
|
2019-05-16 09:52:08 +02:00
|
|
|
label: 'addon.mod_forum.discussionlistsortbycreateddesc',
|
2019-05-07 11:30:56 +02:00
|
|
|
value: AddonModForumProvider.SORTORDER_CREATED_DESC
|
|
|
|
},
|
|
|
|
{
|
2019-05-16 09:52:08 +02:00
|
|
|
label: 'addon.mod_forum.discussionlistsortbycreatedasc',
|
2019-05-07 11:30:56 +02:00
|
|
|
value: AddonModForumProvider.SORTORDER_CREATED_ASC
|
|
|
|
},
|
|
|
|
{
|
2019-05-16 09:52:08 +02:00
|
|
|
label: 'addon.mod_forum.discussionlistsortbyrepliesdesc',
|
2019-05-07 11:30:56 +02:00
|
|
|
value: AddonModForumProvider.SORTORDER_REPLIES_DESC
|
|
|
|
},
|
|
|
|
{
|
2019-05-16 09:52:08 +02:00
|
|
|
label: 'addon.mod_forum.discussionlistsortbyrepliesasc',
|
2019-05-07 11:30:56 +02:00
|
|
|
value: AddonModForumProvider.SORTORDER_REPLIES_ASC
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return sortOrders;
|
|
|
|
}
|
|
|
|
|
2018-05-14 10:18:21 +02:00
|
|
|
/**
|
|
|
|
* Get forum discussions.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param forumId Forum ID.
|
|
|
|
* @param sortOrder Sort order.
|
|
|
|
* @param page Page.
|
|
|
|
* @param forceCache True to always get the value from cache. false otherwise.
|
|
|
|
* @param siteId Site ID. If not defined, current site.
|
|
|
|
* @return Promise resolved with an object with:
|
|
|
|
* - discussions: List of discussions.
|
|
|
|
* - canLoadMore: True if there may be more discussions to load.
|
2018-05-14 10:18:21 +02:00
|
|
|
*/
|
2019-05-07 11:30:56 +02:00
|
|
|
getDiscussions(forumId: number, sortOrder?: number, page: number = 0, forceCache?: boolean, siteId?: string): Promise<any> {
|
|
|
|
sortOrder = sortOrder || AddonModForumProvider.SORTORDER_LASTPOST_DESC;
|
|
|
|
|
2018-05-14 10:18:21 +02:00
|
|
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
2019-05-07 11:30:56 +02:00
|
|
|
let method = 'mod_forum_get_forum_discussions_paginated';
|
|
|
|
const params: any = {
|
2018-05-14 10:18:21 +02:00
|
|
|
forumid: forumId,
|
|
|
|
page: page,
|
|
|
|
perpage: AddonModForumProvider.DISCUSSIONS_PER_PAGE
|
|
|
|
};
|
2019-05-07 11:30:56 +02:00
|
|
|
|
|
|
|
if (site.wsAvailable('mod_forum_get_forum_discussions')) {
|
|
|
|
// Since Moodle 3.7.
|
|
|
|
method = 'mod_forum_get_forum_discussions';
|
|
|
|
params.sortorder = sortOrder;
|
|
|
|
} else {
|
|
|
|
if (sortOrder == AddonModForumProvider.SORTORDER_LASTPOST_DESC) {
|
|
|
|
params.sortby = 'timemodified';
|
|
|
|
params.sortdirection = 'DESC';
|
|
|
|
} else {
|
|
|
|
// Sorting not supported with the old WS method.
|
|
|
|
return Promise.reject(null);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const preSets: CoreSiteWSPreSets = {
|
|
|
|
cacheKey: this.getDiscussionsListCacheKey(forumId, sortOrder)
|
2018-05-14 10:18:21 +02:00
|
|
|
};
|
|
|
|
if (forceCache) {
|
|
|
|
preSets.omitExpires = true;
|
|
|
|
}
|
|
|
|
|
2019-05-07 11:30:56 +02:00
|
|
|
return site.read(method, params, preSets).catch((error) => {
|
|
|
|
// Try to get the data from cache stored with the old WS method.
|
|
|
|
if (!this.appProvider.isOnline() && method == 'mod_forum_get_forum_discussion' &&
|
|
|
|
sortOrder == AddonModForumProvider.SORTORDER_LASTPOST_DESC) {
|
|
|
|
|
|
|
|
const params = {
|
|
|
|
forumid: forumId,
|
|
|
|
page: page,
|
|
|
|
perpage: AddonModForumProvider.DISCUSSIONS_PER_PAGE,
|
|
|
|
sortby: 'timemodified',
|
|
|
|
sortdirection: 'DESC'
|
|
|
|
};
|
|
|
|
const preSets: CoreSiteWSPreSets = {
|
|
|
|
cacheKey: this.getDiscussionsListCacheKey(forumId, sortOrder),
|
|
|
|
omitExpires: true
|
|
|
|
};
|
|
|
|
|
|
|
|
return site.read('mod_forum_get_forum_discussions_paginated', params, preSets);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Promise.reject(error);
|
|
|
|
}).then((response) => {
|
2018-05-14 10:18:21 +02:00
|
|
|
if (response) {
|
|
|
|
this.storeUserData(response.discussions);
|
|
|
|
|
|
|
|
return Promise.resolve({
|
|
|
|
discussions: response.discussions,
|
|
|
|
canLoadMore: response.discussions.length >= AddonModForumProvider.DISCUSSIONS_PER_PAGE,
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
return Promise.reject(null);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get forum discussions in several pages.
|
|
|
|
* If a page fails, the discussions until that page will be returned along with a flag indicating an error occurred.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param forumId Forum ID.
|
|
|
|
* @param sortOrder Sort order.
|
|
|
|
* @param forceCache True to always get the value from cache, false otherwise.
|
|
|
|
* @param numPages Number of pages to get. If not defined, all pages.
|
|
|
|
* @param startPage Page to start. If not defined, first page.
|
|
|
|
* @param siteId Site ID. If not defined, current site.
|
|
|
|
* @return Promise resolved with an object with:
|
|
|
|
* - discussions: List of discussions.
|
|
|
|
* - error: True if an error occurred, false otherwise.
|
2018-05-14 10:18:21 +02:00
|
|
|
*/
|
2019-05-07 11:30:56 +02:00
|
|
|
getDiscussionsInPages(forumId: number, sortOrder?: number, forceCache?: boolean, numPages?: number, startPage?: number,
|
|
|
|
siteId?: string): Promise<any> {
|
2018-05-14 10:18:21 +02:00
|
|
|
if (typeof numPages == 'undefined') {
|
|
|
|
numPages = -1;
|
|
|
|
}
|
|
|
|
startPage = startPage || 0;
|
|
|
|
|
|
|
|
const result = {
|
|
|
|
discussions: [],
|
|
|
|
error: false
|
|
|
|
};
|
|
|
|
|
|
|
|
if (!numPages) {
|
|
|
|
return Promise.resolve(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
const getPage = (page: number): Promise<any> => {
|
|
|
|
// Get page discussions.
|
2019-05-07 11:30:56 +02:00
|
|
|
return this.getDiscussions(forumId, sortOrder, page, forceCache, siteId).then((response) => {
|
2018-05-14 10:18:21 +02:00
|
|
|
result.discussions = result.discussions.concat(response.discussions);
|
|
|
|
numPages--;
|
|
|
|
|
|
|
|
if (response.canLoadMore && numPages !== 0) {
|
|
|
|
return getPage(page + 1); // Get next page.
|
|
|
|
} else {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}).catch(() => {
|
|
|
|
// Error getting a page.
|
|
|
|
result.error = true;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
return getPage(startPage);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Invalidates can add discussion WS calls.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param forumId Forum ID.
|
|
|
|
* @param siteId Site ID. If not defined, current site.
|
|
|
|
* @return Promise resolved when the data is invalidated.
|
2018-05-14 10:18:21 +02:00
|
|
|
*/
|
|
|
|
invalidateCanAddDiscussion(forumId: number, siteId?: string): Promise<any> {
|
|
|
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
|
|
|
return site.invalidateWsCacheForKeyStartingWith(this.getCommonCanAddDiscussionCacheKey(forumId));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Invalidate the prefetched content except files.
|
|
|
|
* To invalidate files, use AddonModForum#invalidateFiles.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param moduleId The module ID.
|
|
|
|
* @param courseId Course ID.
|
|
|
|
* @return Promise resolved when data is invalidated.
|
2018-05-14 10:18:21 +02:00
|
|
|
*/
|
|
|
|
invalidateContent(moduleId: number, courseId: number): Promise<any> {
|
|
|
|
// Get the forum first, we need the forum ID.
|
|
|
|
return this.getForum(courseId, moduleId).then((forum) => {
|
2019-05-07 11:30:56 +02:00
|
|
|
const promises = [];
|
2018-05-14 10:18:21 +02:00
|
|
|
|
2019-05-07 11:30:56 +02:00
|
|
|
promises.push(this.invalidateForumData(courseId));
|
|
|
|
promises.push(this.invalidateDiscussionsList(forum.id));
|
|
|
|
promises.push(this.invalidateCanAddDiscussion(forum.id));
|
|
|
|
promises.push(this.invalidateAccessInformation(forum.id));
|
2018-05-14 10:18:21 +02:00
|
|
|
|
2019-05-07 11:30:56 +02:00
|
|
|
this.getAvailableSortOrders().forEach((sortOrder) => {
|
|
|
|
// We need to get the list of discussions to be able to invalidate their posts.
|
|
|
|
promises.push(this.getDiscussionsInPages(forum.id, sortOrder.value, true).then((response) => {
|
|
|
|
// Now invalidate the WS calls.
|
|
|
|
const promises = [];
|
2018-05-14 10:18:21 +02:00
|
|
|
|
2019-05-07 11:30:56 +02:00
|
|
|
response.discussions.forEach((discussion) => {
|
|
|
|
promises.push(this.invalidateDiscussionPosts(discussion.discussion));
|
|
|
|
});
|
|
|
|
|
|
|
|
return this.utils.allPromises(promises);
|
|
|
|
}));
|
2018-05-14 10:18:21 +02:00
|
|
|
});
|
2019-05-07 11:30:56 +02:00
|
|
|
|
|
|
|
if (this.isDiscussionListSortingAvailable()) {
|
|
|
|
promises.push(this.userProvider.invalidateUserPreference(AddonModForumProvider.PREFERENCE_SORTORDER));
|
|
|
|
}
|
|
|
|
|
|
|
|
return this.utils.allPromises(promises);
|
2018-05-14 10:18:21 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-04-09 15:35:24 +02:00
|
|
|
/**
|
|
|
|
* Invalidates access information.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param forumId Forum ID.
|
|
|
|
* @param siteId Site ID. If not defined, current site.
|
|
|
|
* @return Promise resolved when the data is invalidated.
|
2019-04-09 15:35:24 +02:00
|
|
|
*/
|
|
|
|
invalidateAccessInformation(forumId: number, siteId?: string): Promise<any> {
|
|
|
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
|
|
|
return site.invalidateWsCacheForKey(this.getAccessInformationCacheKey(forumId));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-05-14 10:18:21 +02:00
|
|
|
/**
|
|
|
|
* Invalidates forum discussion posts.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param discussionId Discussion ID.
|
|
|
|
* @param siteId Site ID. If not defined, current site.
|
|
|
|
* @return Promise resolved when the data is invalidated.
|
2018-05-14 10:18:21 +02:00
|
|
|
*/
|
|
|
|
invalidateDiscussionPosts(discussionId: number, siteId?: string): Promise<any> {
|
|
|
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
|
|
|
return site.invalidateWsCacheForKey(this.getDiscussionPostsCacheKey(discussionId));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Invalidates discussion list.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param forumId Forum ID.
|
|
|
|
* @param siteId Site ID. If not defined, current site.
|
|
|
|
* @return Promise resolved when the data is invalidated.
|
2018-05-14 10:18:21 +02:00
|
|
|
*/
|
|
|
|
invalidateDiscussionsList(forumId: number, siteId?: string): Promise<any> {
|
|
|
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
2019-05-07 11:30:56 +02:00
|
|
|
return this.utils.allPromises(this.getAvailableSortOrders().map((sortOrder) => {
|
|
|
|
return site.invalidateWsCacheForKey(this.getDiscussionsListCacheKey(forumId, sortOrder.value));
|
|
|
|
}));
|
2018-05-14 10:18:21 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Invalidate the prefetched files.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param moduleId The module ID.
|
|
|
|
* @return Promise resolved when the files are invalidated.
|
2018-05-14 10:18:21 +02:00
|
|
|
*/
|
|
|
|
invalidateFiles(moduleId: number): Promise<any> {
|
|
|
|
const siteId = this.sitesProvider.getCurrentSiteId();
|
|
|
|
|
|
|
|
return this.filepoolProvider.invalidateFilesByComponent(siteId, AddonModForumProvider.COMPONENT, moduleId);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Invalidates forum data.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param courseId Course ID.
|
|
|
|
* @return Promise resolved when the data is invalidated.
|
2018-05-14 10:18:21 +02:00
|
|
|
*/
|
|
|
|
invalidateForumData(courseId: number): Promise<any> {
|
|
|
|
return this.sitesProvider.getCurrentSite().invalidateWsCacheForKey(this.getForumDataCacheKey(courseId));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Report a forum as being viewed.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param id Module ID.
|
|
|
|
* @param name Name of the forum.
|
|
|
|
* @param siteId Site ID. If not defined, current site.
|
|
|
|
* @return Promise resolved when the WS call is successful.
|
2018-05-14 10:18:21 +02:00
|
|
|
*/
|
2019-05-03 09:36:42 +02:00
|
|
|
logView(id: number, name?: string, siteId?: string): Promise<any> {
|
2018-05-14 10:18:21 +02:00
|
|
|
const params = {
|
|
|
|
forumid: id
|
|
|
|
};
|
|
|
|
|
2019-05-03 09:36:42 +02:00
|
|
|
return this.logHelper.logSingle('mod_forum_view_forum', params, AddonModForumProvider.COMPONENT, id, name, 'forum', {},
|
|
|
|
siteId);
|
2018-05-14 10:18:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Report a forum discussion as being viewed.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param id Discussion ID.
|
|
|
|
* @param forumId Forum ID.
|
|
|
|
* @param name Name of the forum.
|
|
|
|
* @param siteId Site ID. If not defined, current site.
|
|
|
|
* @return Promise resolved when the WS call is successful.
|
2018-05-14 10:18:21 +02:00
|
|
|
*/
|
2019-05-03 09:36:42 +02:00
|
|
|
logDiscussionView(id: number, forumId: number, name?: string, siteId?: string): Promise<any> {
|
2018-05-14 10:18:21 +02:00
|
|
|
const params = {
|
|
|
|
discussionid: id
|
|
|
|
};
|
|
|
|
|
2019-05-03 09:36:42 +02:00
|
|
|
return this.logHelper.logSingle('mod_forum_view_forum_discussion', params, AddonModForumProvider.COMPONENT, forumId, name,
|
|
|
|
'forum', params, siteId);
|
2018-05-14 10:18:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reply to a certain post.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param postId ID of the post being replied.
|
|
|
|
* @param discussionId ID of the discussion the user is replying to.
|
|
|
|
* @param forumId ID of the forum the user is replying to.
|
|
|
|
* @param name Forum name.
|
|
|
|
* @param courseId Course ID the forum belongs to.
|
|
|
|
* @param subject New post's subject.
|
|
|
|
* @param message New post's message.
|
|
|
|
* @param options Options (subscribe, attachments, ...).
|
|
|
|
* @param siteId Site ID. If not defined, current site.
|
|
|
|
* @param allowOffline True if it can be stored in offline, false otherwise.
|
|
|
|
* @return Promise resolved with post ID if sent online, resolved with false if stored offline.
|
2018-05-14 10:18:21 +02:00
|
|
|
*/
|
|
|
|
replyPost(postId: number, discussionId: number, forumId: number, name: string, courseId: number, subject: string,
|
|
|
|
message: string, options?: any, siteId?: string, allowOffline?: boolean): Promise<any> {
|
|
|
|
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
|
|
|
|
|
|
|
// Convenience function to store a message to be synchronized later.
|
|
|
|
const storeOffline = (): Promise<boolean> => {
|
|
|
|
if (!forumId) {
|
|
|
|
// Not enough data to store in offline, reject.
|
|
|
|
return Promise.reject(this.translate.instant('core.networkerrormsg'));
|
|
|
|
}
|
|
|
|
|
|
|
|
return this.forumOffline.replyPost(postId, discussionId, forumId, name, courseId, subject, message, options, siteId)
|
|
|
|
.then(() => {
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
if (!this.appProvider.isOnline() && allowOffline) {
|
|
|
|
// App is offline, store the action.
|
|
|
|
return storeOffline();
|
|
|
|
}
|
|
|
|
|
|
|
|
// If there's already a reply to be sent to the server, discard it first.
|
|
|
|
return this.forumOffline.deleteReply(postId, siteId).then(() => {
|
|
|
|
|
|
|
|
return this.replyPostOnline(postId, subject, message, options, siteId).then(() => {
|
|
|
|
return true;
|
|
|
|
}).catch((error) => {
|
|
|
|
if (allowOffline && !this.utils.isWebServiceError(error)) {
|
|
|
|
// Couldn't connect to server, store in offline.
|
|
|
|
return storeOffline();
|
|
|
|
} else {
|
|
|
|
// The WebService has thrown an error or offline not supported, reject.
|
|
|
|
return Promise.reject(error);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reply to a certain post. It will fail if offline or cannot connect.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param postId ID of the post being replied.
|
|
|
|
* @param subject New post's subject.
|
|
|
|
* @param message New post's message.
|
|
|
|
* @param options Options (subscribe, attachments, ...).
|
|
|
|
* @param siteId Site ID. If not defined, current site.
|
|
|
|
* @return Promise resolved with the created post id.
|
2018-05-14 10:18:21 +02:00
|
|
|
*/
|
|
|
|
replyPostOnline(postId: number, subject: string, message: string, options?: any, siteId?: string): Promise<number> {
|
|
|
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
|
|
|
const params = {
|
|
|
|
postid: postId,
|
|
|
|
subject: subject,
|
|
|
|
message: message,
|
|
|
|
options: this.utils.objectToArrayOfObjects(options, 'name', 'value')
|
|
|
|
};
|
|
|
|
|
|
|
|
return site.write('mod_forum_add_discussion_post', params).then((response) => {
|
|
|
|
if (!response || !response.postid) {
|
2018-05-30 11:32:54 +02:00
|
|
|
return Promise.reject(this.utils.createFakeWSError(''));
|
2018-05-14 10:18:21 +02:00
|
|
|
} else {
|
|
|
|
return response.postid;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
2019-04-16 16:55:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Lock or unlock a discussion.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param forumId Forum id.
|
|
|
|
* @param discussionId DIscussion id.
|
|
|
|
* @param locked True to lock, false to unlock.
|
|
|
|
* @param siteId Site ID. If not defined, current site.
|
|
|
|
* @return Promise resvoled when done.
|
2019-04-16 16:55:33 +02:00
|
|
|
* @since 3.7
|
|
|
|
*/
|
|
|
|
setLockState(forumId: number, discussionId: number, locked: boolean, siteId?: string): Promise<any> {
|
|
|
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
|
|
|
const params = {
|
|
|
|
forumid: forumId,
|
|
|
|
discussionid: discussionId,
|
|
|
|
targetstate: locked ? 0 : 1
|
|
|
|
};
|
|
|
|
|
|
|
|
return site.write('mod_forum_set_lock_state', params);
|
|
|
|
});
|
2019-04-30 12:57:44 +02:00
|
|
|
}
|
|
|
|
|
2019-05-02 10:42:46 +02:00
|
|
|
/**
|
|
|
|
* Returns whether the set pin state WS is available.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param site Site. If not defined, current site.
|
|
|
|
* @return Whether it's available.
|
2019-05-02 10:42:46 +02:00
|
|
|
* @since 3.7
|
|
|
|
*/
|
|
|
|
isSetPinStateAvailableForSite(site?: CoreSite): boolean {
|
|
|
|
site = site || this.sitesProvider.getCurrentSite();
|
|
|
|
|
|
|
|
return this.sitesProvider.wsAvailableInCurrentSite('mod_forum_set_pin_state');
|
|
|
|
}
|
|
|
|
|
2019-04-30 12:57:44 +02:00
|
|
|
/**
|
|
|
|
* Pin or unpin a discussion.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param discussionId Discussion id.
|
|
|
|
* @param locked True to pin, false to unpin.
|
|
|
|
* @param siteId Site ID. If not defined, current site.
|
|
|
|
* @return Promise resvoled when done.
|
2019-04-30 12:57:44 +02:00
|
|
|
* @since 3.7
|
|
|
|
*/
|
|
|
|
setPinState(discussionId: number, pinned: boolean, siteId?: string): Promise<any> {
|
|
|
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
|
|
|
const params = {
|
|
|
|
discussionid: discussionId,
|
|
|
|
targetstate: pinned ? 1 : 0
|
|
|
|
};
|
|
|
|
|
|
|
|
return site.write('mod_forum_set_pin_state', params);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Star or unstar a discussion.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param discussionId Discussion id.
|
|
|
|
* @param starred True to star, false to unstar.
|
|
|
|
* @param siteId Site ID. If not defined, current site.
|
|
|
|
* @return Promise resvoled when done.
|
2019-04-30 12:57:44 +02:00
|
|
|
* @since 3.7
|
|
|
|
*/
|
|
|
|
toggleFavouriteState(discussionId: number, starred: boolean, siteId?: string): Promise<any> {
|
|
|
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
|
|
|
const params = {
|
|
|
|
discussionid: discussionId,
|
|
|
|
targetstate: starred ? 1 : 0
|
|
|
|
};
|
|
|
|
|
|
|
|
return site.write('mod_forum_toggle_favourite_state', params);
|
|
|
|
});
|
2018-05-14 10:18:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Store the users data from a discussions/posts list.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param list Array of posts or discussions.
|
2018-05-14 10:18:21 +02:00
|
|
|
*/
|
|
|
|
protected storeUserData(list: any[]): void {
|
|
|
|
const users = {};
|
|
|
|
|
|
|
|
list.forEach((entry) => {
|
|
|
|
const userId = parseInt(entry.userid);
|
|
|
|
if (!isNaN(userId) && !users[userId]) {
|
|
|
|
users[userId] = {
|
|
|
|
id: userId,
|
|
|
|
fullname: entry.userfullname,
|
|
|
|
profileimageurl: entry.userpictureurl
|
|
|
|
};
|
|
|
|
}
|
|
|
|
const userModified = parseInt(entry.usermodified);
|
|
|
|
if (!isNaN(userModified) && !users[userModified]) {
|
|
|
|
users[userModified] = {
|
|
|
|
id: userModified,
|
|
|
|
fullname: entry.usermodifiedfullname,
|
|
|
|
profileimageurl: entry.usermodifiedpictureurl
|
|
|
|
};
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
this.userProvider.storeUsers(this.utils.objectToArray(users));
|
|
|
|
}
|
|
|
|
}
|