Commit | Line | Data |
---|---|---|
2b9fe87d MN |
1 | <?php |
2 | ||
3 | // This file is part of Moodle - http://moodle.org/ | |
4 | // | |
5 | // Moodle is free software: you can redistribute it and/or modify | |
6 | // it under the terms of the GNU General Public License as published by | |
7 | // the Free Software Foundation, either version 3 of the License, or | |
8 | // (at your option) any later version. | |
9 | // | |
10 | // Moodle is distributed in the hope that it will be useful, | |
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | // GNU General Public License for more details. | |
14 | // | |
15 | // You should have received a copy of the GNU General Public License | |
16 | // along with Moodle. If not, see <http://www.gnu.org/licenses/>. | |
17 | ||
18 | /** | |
19 | * External forum API | |
20 | * | |
21 | * @package mod_forum | |
22 | * @copyright 2012 Mark Nelson <markn@moodle.com> | |
23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
24 | */ | |
25 | ||
26 | defined('MOODLE_INTERNAL') || die; | |
27 | ||
28 | require_once("$CFG->libdir/externallib.php"); | |
29 | ||
30 | class mod_forum_external extends external_api { | |
31 | ||
32 | /** | |
a9a0cb69 | 33 | * Describes the parameters for get_forum. |
2b9fe87d MN |
34 | * |
35 | * @return external_external_function_parameters | |
36 | * @since Moodle 2.5 | |
37 | */ | |
38 | public static function get_forums_by_courses_parameters() { | |
39 | return new external_function_parameters ( | |
40 | array( | |
41 | 'courseids' => new external_multiple_structure(new external_value(PARAM_INT, 'course ID', | |
a9a0cb69 | 42 | '', VALUE_REQUIRED, '', NULL_NOT_ALLOWED), 'Array of Course IDs', VALUE_DEFAULT, array()), |
2b9fe87d MN |
43 | ) |
44 | ); | |
45 | } | |
46 | ||
47 | /** | |
48 | * Returns a list of forums in a provided list of courses, | |
49 | * if no list is provided all forums that the user can view | |
50 | * will be returned. | |
51 | * | |
52 | * @param array $courseids the course ids | |
53 | * @return array the forum details | |
54 | * @since Moodle 2.5 | |
55 | */ | |
56 | public static function get_forums_by_courses($courseids = array()) { | |
c8f1d8a0 | 57 | global $CFG; |
2b9fe87d MN |
58 | |
59 | require_once($CFG->dirroot . "/mod/forum/lib.php"); | |
60 | ||
a9a0cb69 MN |
61 | $params = self::validate_parameters(self::get_forums_by_courses_parameters(), array('courseids' => $courseids)); |
62 | ||
63 | if (empty($params['courseids'])) { | |
2b9fe87d MN |
64 | // Get all the courses the user can view. |
65 | $courseids = array_keys(enrol_get_my_courses()); | |
66 | } else { | |
2b9fe87d MN |
67 | $courseids = $params['courseids']; |
68 | } | |
69 | ||
70 | // Array to store the forums to return. | |
71 | $arrforums = array(); | |
72 | ||
0c246ae5 | 73 | // Ensure there are courseids to loop through. |
2b9fe87d | 74 | if (!empty($courseids)) { |
c8f1d8a0 JL |
75 | // Array of the courses we are going to retrieve the forums from. |
76 | $dbcourses = array(); | |
77 | // Mod info for courses. | |
78 | $modinfocourses = array(); | |
79 | ||
0c246ae5 | 80 | // Go through the courseids and return the forums. |
c8f1d8a0 | 81 | foreach ($courseids as $courseid) { |
0c246ae5 | 82 | // Check the user can function in this context. |
c8f1d8a0 JL |
83 | try { |
84 | $context = context_course::instance($courseid); | |
85 | self::validate_context($context); | |
0c246ae5 | 86 | // Get the modinfo for the course. |
c8f1d8a0 JL |
87 | $modinfocourses[$courseid] = get_fast_modinfo($courseid); |
88 | $dbcourses[$courseid] = $modinfocourses[$courseid]->get_course(); | |
89 | ||
90 | } catch (Exception $e) { | |
91 | continue; | |
92 | } | |
93 | } | |
94 | ||
95 | // Get the forums in this course. This function checks users visibility permissions. | |
96 | if ($forums = get_all_instances_in_courses("forum", $dbcourses)) { | |
97 | foreach ($forums as $forum) { | |
98 | ||
99 | $course = $dbcourses[$forum->course]; | |
100 | $cm = $modinfocourses[$course->id]->get_cm($forum->coursemodule); | |
101 | $context = context_module::instance($cm->id); | |
102 | ||
103 | // Skip forums we are not allowed to see discussions. | |
104 | if (!has_capability('mod/forum:viewdiscussion', $context)) { | |
105 | continue; | |
2b9fe87d | 106 | } |
c8f1d8a0 JL |
107 | |
108 | // Format the intro before being returning using the format setting. | |
109 | list($forum->intro, $forum->introformat) = external_format_text($forum->intro, $forum->introformat, | |
110 | $context->id, 'mod_forum', 'intro', 0); | |
111 | // Discussions count. This function does static request cache. | |
112 | $forum->numdiscussions = forum_count_discussions($forum, $cm, $course); | |
113 | $forum->cmid = $forum->coursemodule; | |
114 | ||
115 | // Add the forum to the array to return. | |
116 | $arrforums[$forum->id] = $forum; | |
2b9fe87d MN |
117 | } |
118 | } | |
119 | } | |
120 | ||
121 | return $arrforums; | |
122 | } | |
123 | ||
124 | /** | |
a9a0cb69 | 125 | * Describes the get_forum return value. |
2b9fe87d MN |
126 | * |
127 | * @return external_single_structure | |
128 | * @since Moodle 2.5 | |
129 | */ | |
130 | public static function get_forums_by_courses_returns() { | |
131 | return new external_multiple_structure( | |
132 | new external_single_structure( | |
133 | array( | |
134 | 'id' => new external_value(PARAM_INT, 'Forum id'), | |
135 | 'course' => new external_value(PARAM_TEXT, 'Course id'), | |
136 | 'type' => new external_value(PARAM_TEXT, 'The forum type'), | |
137 | 'name' => new external_value(PARAM_TEXT, 'Forum name'), | |
138 | 'intro' => new external_value(PARAM_RAW, 'The forum intro'), | |
139 | 'introformat' => new external_format_value('intro'), | |
140 | 'assessed' => new external_value(PARAM_INT, 'Aggregate type'), | |
141 | 'assesstimestart' => new external_value(PARAM_INT, 'Assess start time'), | |
142 | 'assesstimefinish' => new external_value(PARAM_INT, 'Assess finish time'), | |
143 | 'scale' => new external_value(PARAM_INT, 'Scale'), | |
144 | 'maxbytes' => new external_value(PARAM_INT, 'Maximum attachment size'), | |
145 | 'maxattachments' => new external_value(PARAM_INT, 'Maximum number of attachments'), | |
146 | 'forcesubscribe' => new external_value(PARAM_INT, 'Force users to subscribe'), | |
147 | 'trackingtype' => new external_value(PARAM_INT, 'Subscription mode'), | |
148 | 'rsstype' => new external_value(PARAM_INT, 'RSS feed for this activity'), | |
149 | 'rssarticles' => new external_value(PARAM_INT, 'Number of RSS recent articles'), | |
150 | 'timemodified' => new external_value(PARAM_INT, 'Time modified'), | |
151 | 'warnafter' => new external_value(PARAM_INT, 'Post threshold for warning'), | |
152 | 'blockafter' => new external_value(PARAM_INT, 'Post threshold for blocking'), | |
153 | 'blockperiod' => new external_value(PARAM_INT, 'Time period for blocking'), | |
154 | 'completiondiscussions' => new external_value(PARAM_INT, 'Student must create discussions'), | |
155 | 'completionreplies' => new external_value(PARAM_INT, 'Student must post replies'), | |
156 | 'completionposts' => new external_value(PARAM_INT, 'Student must post discussions or replies'), | |
7ea6ada3 JL |
157 | 'cmid' => new external_value(PARAM_INT, 'Course module id'), |
158 | 'numdiscussions' => new external_value(PARAM_INT, 'Number of discussions in the forum', VALUE_OPTIONAL) | |
2b9fe87d MN |
159 | ), 'forum' |
160 | ) | |
161 | ); | |
162 | } | |
a9a0cb69 MN |
163 | |
164 | /** | |
165 | * Describes the parameters for get_forum_discussions. | |
166 | * | |
167 | * @return external_external_function_parameters | |
168 | * @since Moodle 2.5 | |
ef8a44de JL |
169 | * @deprecated Moodle 2.8 MDL-46458 - Please do not call this function any more. |
170 | * @see get_forum_discussions_paginated | |
a9a0cb69 MN |
171 | */ |
172 | public static function get_forum_discussions_parameters() { | |
173 | return new external_function_parameters ( | |
174 | array( | |
175 | 'forumids' => new external_multiple_structure(new external_value(PARAM_INT, 'forum ID', | |
176 | '', VALUE_REQUIRED, '', NULL_NOT_ALLOWED), 'Array of Forum IDs', VALUE_REQUIRED), | |
dc14212b MG |
177 | 'limitfrom' => new external_value(PARAM_INT, 'limit from', VALUE_DEFAULT, 0), |
178 | 'limitnum' => new external_value(PARAM_INT, 'limit number', VALUE_DEFAULT, 0) | |
a9a0cb69 MN |
179 | ) |
180 | ); | |
181 | } | |
182 | ||
183 | /** | |
184 | * Returns a list of forum discussions as well as a summary of the discussion | |
185 | * in a provided list of forums. | |
186 | * | |
187 | * @param array $forumids the forum ids | |
1fee2cd4 JL |
188 | * @param int $limitfrom limit from SQL data |
189 | * @param int $limitnum limit number SQL data | |
190 | * | |
a9a0cb69 MN |
191 | * @return array the forum discussion details |
192 | * @since Moodle 2.5 | |
ef8a44de JL |
193 | * @deprecated Moodle 2.8 MDL-46458 - Please do not call this function any more. |
194 | * @see get_forum_discussions_paginated | |
a9a0cb69 | 195 | */ |
1fee2cd4 | 196 | public static function get_forum_discussions($forumids, $limitfrom = 0, $limitnum = 0) { |
a9a0cb69 MN |
197 | global $CFG, $DB, $USER; |
198 | ||
199 | require_once($CFG->dirroot . "/mod/forum/lib.php"); | |
200 | ||
201 | // Validate the parameter. | |
1fee2cd4 JL |
202 | $params = self::validate_parameters(self::get_forum_discussions_parameters(), |
203 | array( | |
204 | 'forumids' => $forumids, | |
205 | 'limitfrom' => $limitfrom, | |
206 | 'limitnum' => $limitnum, | |
207 | )); | |
208 | $forumids = $params['forumids']; | |
209 | $limitfrom = $params['limitfrom']; | |
210 | $limitnum = $params['limitnum']; | |
a9a0cb69 MN |
211 | |
212 | // Array to store the forum discussions to return. | |
213 | $arrdiscussions = array(); | |
a9a0cb69 MN |
214 | // Keep track of the users we have looked up in the DB. |
215 | $arrusers = array(); | |
216 | ||
217 | // Loop through them. | |
218 | foreach ($forumids as $id) { | |
219 | // Get the forum object. | |
220 | $forum = $DB->get_record('forum', array('id' => $id), '*', MUST_EXIST); | |
40afeb40 JL |
221 | $course = get_course($forum->course); |
222 | ||
223 | $modinfo = get_fast_modinfo($course); | |
224 | $forums = $modinfo->get_instances_of('forum'); | |
225 | $cm = $forums[$forum->id]; | |
226 | ||
a9a0cb69 MN |
227 | // Get the module context. |
228 | $modcontext = context_module::instance($cm->id); | |
40afeb40 JL |
229 | |
230 | // Validate the context. | |
231 | self::validate_context($modcontext); | |
232 | ||
a9a0cb69 | 233 | require_capability('mod/forum:viewdiscussion', $modcontext); |
40afeb40 JL |
234 | |
235 | // Get the discussions for this forum. | |
236 | $params = array(); | |
237 | ||
238 | $groupselect = ""; | |
239 | $groupmode = groups_get_activity_groupmode($cm, $course); | |
240 | ||
241 | if ($groupmode and $groupmode != VISIBLEGROUPS and !has_capability('moodle/site:accessallgroups', $modcontext)) { | |
242 | // Get all the discussions from all the groups this user belongs to. | |
243 | $usergroups = groups_get_user_groups($course->id); | |
244 | if (!empty($usergroups['0'])) { | |
245 | list($sql, $params) = $DB->get_in_or_equal($usergroups['0']); | |
246 | $groupselect = "AND (groupid $sql OR groupid = -1)"; | |
a9a0cb69 MN |
247 | } |
248 | } | |
40afeb40 JL |
249 | array_unshift($params, $id); |
250 | $select = "forum = ? $groupselect"; | |
251 | ||
252 | if ($discussions = $DB->get_records_select('forum_discussions', $select, $params, 'timemodified DESC', '*', | |
253 | $limitfrom, $limitnum)) { | |
254 | ||
255 | // Check if they can view full names. | |
256 | $canviewfullname = has_capability('moodle/site:viewfullnames', $modcontext); | |
257 | // Get the unreads array, this takes a forum id and returns data for all discussions. | |
258 | $unreads = array(); | |
259 | if ($cantrack = forum_tp_can_track_forums($forum)) { | |
260 | if ($forumtracked = forum_tp_is_tracked($forum)) { | |
261 | $unreads = forum_get_discussions_unread($cm); | |
262 | } | |
263 | } | |
264 | // The forum function returns the replies for all the discussions in a given forum. | |
265 | $replies = forum_count_discussion_replies($id); | |
266 | ||
a9a0cb69 | 267 | foreach ($discussions as $discussion) { |
40afeb40 JL |
268 | // This function checks capabilities, timed discussions, groups and qanda forums posting. |
269 | if (!forum_user_can_see_discussion($forum, $discussion, $modcontext)) { | |
270 | continue; | |
a9a0cb69 | 271 | } |
40afeb40 | 272 | |
94b1577a | 273 | $usernamefields = user_picture::fields(); |
a9a0cb69 MN |
274 | // If we don't have the users details then perform DB call. |
275 | if (empty($arrusers[$discussion->userid])) { | |
276 | $arrusers[$discussion->userid] = $DB->get_record('user', array('id' => $discussion->userid), | |
94b1577a | 277 | $usernamefields, MUST_EXIST); |
a9a0cb69 MN |
278 | } |
279 | // Get the subject. | |
280 | $subject = $DB->get_field('forum_posts', 'subject', array('id' => $discussion->firstpost), MUST_EXIST); | |
281 | // Create object to return. | |
282 | $return = new stdClass(); | |
283 | $return->id = (int) $discussion->id; | |
284 | $return->course = $discussion->course; | |
285 | $return->forum = $discussion->forum; | |
286 | $return->name = $discussion->name; | |
287 | $return->userid = $discussion->userid; | |
288 | $return->groupid = $discussion->groupid; | |
289 | $return->assessed = $discussion->assessed; | |
290 | $return->timemodified = (int) $discussion->timemodified; | |
291 | $return->usermodified = $discussion->usermodified; | |
292 | $return->timestart = $discussion->timestart; | |
293 | $return->timeend = $discussion->timeend; | |
294 | $return->firstpost = (int) $discussion->firstpost; | |
295 | $return->firstuserfullname = fullname($arrusers[$discussion->userid], $canviewfullname); | |
296 | $return->firstuserimagealt = $arrusers[$discussion->userid]->imagealt; | |
297 | $return->firstuserpicture = $arrusers[$discussion->userid]->picture; | |
298 | $return->firstuseremail = $arrusers[$discussion->userid]->email; | |
299 | $return->subject = $subject; | |
300 | $return->numunread = ''; | |
301 | if ($cantrack && $forumtracked) { | |
302 | if (isset($unreads[$discussion->id])) { | |
303 | $return->numunread = (int) $unreads[$discussion->id]; | |
304 | } | |
305 | } | |
306 | // Check if there are any replies to this discussion. | |
307 | if (!empty($replies[$discussion->id])) { | |
308 | $return->numreplies = (int) $replies[$discussion->id]->replies; | |
309 | $return->lastpost = (int) $replies[$discussion->id]->lastpostid; | |
40afeb40 | 310 | } else { // No replies, so the last post will be the first post. |
a9a0cb69 MN |
311 | $return->numreplies = 0; |
312 | $return->lastpost = (int) $discussion->firstpost; | |
40afeb40 | 313 | } |
a9a0cb69 MN |
314 | // Get the last post as well as the user who made it. |
315 | $lastpost = $DB->get_record('forum_posts', array('id' => $return->lastpost), '*', MUST_EXIST); | |
316 | if (empty($arrusers[$lastpost->userid])) { | |
317 | $arrusers[$lastpost->userid] = $DB->get_record('user', array('id' => $lastpost->userid), | |
94b1577a | 318 | $usernamefields, MUST_EXIST); |
a9a0cb69 MN |
319 | } |
320 | $return->lastuserid = $lastpost->userid; | |
321 | $return->lastuserfullname = fullname($arrusers[$lastpost->userid], $canviewfullname); | |
322 | $return->lastuserimagealt = $arrusers[$lastpost->userid]->imagealt; | |
323 | $return->lastuserpicture = $arrusers[$lastpost->userid]->picture; | |
324 | $return->lastuseremail = $arrusers[$lastpost->userid]->email; | |
325 | // Add the discussion statistics to the array to return. | |
326 | $arrdiscussions[$return->id] = (array) $return; | |
327 | } | |
328 | } | |
329 | } | |
330 | ||
331 | return $arrdiscussions; | |
332 | } | |
333 | ||
334 | /** | |
335 | * Describes the get_forum_discussions return value. | |
336 | * | |
337 | * @return external_single_structure | |
338 | * @since Moodle 2.5 | |
ef8a44de JL |
339 | * @deprecated Moodle 2.8 MDL-46458 - Please do not call this function any more. |
340 | * @see get_forum_discussions_paginated | |
a9a0cb69 MN |
341 | */ |
342 | public static function get_forum_discussions_returns() { | |
343 | return new external_multiple_structure( | |
344 | new external_single_structure( | |
345 | array( | |
346 | 'id' => new external_value(PARAM_INT, 'Forum id'), | |
347 | 'course' => new external_value(PARAM_INT, 'Course id'), | |
348 | 'forum' => new external_value(PARAM_INT, 'The forum id'), | |
349 | 'name' => new external_value(PARAM_TEXT, 'Discussion name'), | |
350 | 'userid' => new external_value(PARAM_INT, 'User id'), | |
351 | 'groupid' => new external_value(PARAM_INT, 'Group id'), | |
352 | 'assessed' => new external_value(PARAM_INT, 'Is this assessed?'), | |
353 | 'timemodified' => new external_value(PARAM_INT, 'Time modified'), | |
354 | 'usermodified' => new external_value(PARAM_INT, 'The id of the user who last modified'), | |
355 | 'timestart' => new external_value(PARAM_INT, 'Time discussion can start'), | |
356 | 'timeend' => new external_value(PARAM_INT, 'Time discussion ends'), | |
357 | 'firstpost' => new external_value(PARAM_INT, 'The first post in the discussion'), | |
358 | 'firstuserfullname' => new external_value(PARAM_TEXT, 'The discussion creators fullname'), | |
359 | 'firstuserimagealt' => new external_value(PARAM_TEXT, 'The discussion creators image alt'), | |
360 | 'firstuserpicture' => new external_value(PARAM_INT, 'The discussion creators profile picture'), | |
361 | 'firstuseremail' => new external_value(PARAM_TEXT, 'The discussion creators email'), | |
362 | 'subject' => new external_value(PARAM_TEXT, 'The discussion subject'), | |
363 | 'numreplies' => new external_value(PARAM_TEXT, 'The number of replies in the discussion'), | |
364 | 'numunread' => new external_value(PARAM_TEXT, 'The number of unread posts, blank if this value is | |
365 | not available due to forum settings.'), | |
366 | 'lastpost' => new external_value(PARAM_INT, 'The id of the last post in the discussion'), | |
367 | 'lastuserid' => new external_value(PARAM_INT, 'The id of the user who made the last post'), | |
368 | 'lastuserfullname' => new external_value(PARAM_TEXT, 'The last person to posts fullname'), | |
369 | 'lastuserimagealt' => new external_value(PARAM_TEXT, 'The last person to posts image alt'), | |
370 | 'lastuserpicture' => new external_value(PARAM_INT, 'The last person to posts profile picture'), | |
371 | 'lastuseremail' => new external_value(PARAM_TEXT, 'The last person to posts email'), | |
372 | ), 'discussion' | |
373 | ) | |
374 | ); | |
375 | } | |
e2ede426 JL |
376 | |
377 | /** | |
378 | * Describes the parameters for get_forum_discussion_posts. | |
379 | * | |
380 | * @return external_external_function_parameters | |
381 | * @since Moodle 2.7 | |
382 | */ | |
383 | public static function get_forum_discussion_posts_parameters() { | |
384 | return new external_function_parameters ( | |
385 | array( | |
386 | 'discussionid' => new external_value(PARAM_INT, 'discussion ID', VALUE_REQUIRED), | |
387 | 'sortby' => new external_value(PARAM_ALPHA, | |
388 | 'sort by this element: id, created or modified', VALUE_DEFAULT, 'created'), | |
389 | 'sortdirection' => new external_value(PARAM_ALPHA, 'sort direction: ASC or DESC', VALUE_DEFAULT, 'DESC') | |
390 | ) | |
391 | ); | |
392 | } | |
393 | ||
394 | /** | |
395 | * Returns a list of forum posts for a discussion | |
396 | * | |
397 | * @param int $discussionid the post ids | |
398 | * @param string $sortby sort by this element (id, created or modified) | |
399 | * @param string $sortdirection sort direction: ASC or DESC | |
400 | * | |
401 | * @return array the forum post details | |
402 | * @since Moodle 2.7 | |
403 | */ | |
fb8840d2 | 404 | public static function get_forum_discussion_posts($discussionid, $sortby = "created", $sortdirection = "DESC") { |
e2ede426 JL |
405 | global $CFG, $DB, $USER; |
406 | ||
b1aa7dfa | 407 | $posts = array(); |
e2ede426 JL |
408 | $warnings = array(); |
409 | ||
410 | // Validate the parameter. | |
411 | $params = self::validate_parameters(self::get_forum_discussion_posts_parameters(), | |
412 | array( | |
413 | 'discussionid' => $discussionid, | |
414 | 'sortby' => $sortby, | |
415 | 'sortdirection' => $sortdirection)); | |
416 | ||
417 | // Compact/extract functions are not recommended. | |
418 | $discussionid = $params['discussionid']; | |
419 | $sortby = $params['sortby']; | |
420 | $sortdirection = $params['sortdirection']; | |
421 | ||
422 | $sortallowedvalues = array('id', 'created', 'modified'); | |
423 | if (!in_array($sortby, $sortallowedvalues)) { | |
424 | throw new invalid_parameter_exception('Invalid value for sortby parameter (value: ' . $sortby . '),' . | |
425 | 'allowed values are: ' . implode(',', $sortallowedvalues)); | |
426 | } | |
427 | ||
428 | $sortdirection = strtoupper($sortdirection); | |
429 | $directionallowedvalues = array('ASC', 'DESC'); | |
430 | if (!in_array($sortdirection, $directionallowedvalues)) { | |
431 | throw new invalid_parameter_exception('Invalid value for sortdirection parameter (value: ' . $sortdirection . '),' . | |
432 | 'allowed values are: ' . implode(',', $directionallowedvalues)); | |
433 | } | |
434 | ||
435 | $discussion = $DB->get_record('forum_discussions', array('id' => $discussionid), '*', MUST_EXIST); | |
436 | $forum = $DB->get_record('forum', array('id' => $discussion->forum), '*', MUST_EXIST); | |
437 | $course = $DB->get_record('course', array('id' => $forum->course), '*', MUST_EXIST); | |
438 | $cm = get_coursemodule_from_instance('forum', $forum->id, $course->id, false, MUST_EXIST); | |
439 | ||
440 | // Validate the module context. It checks everything that affects the module visibility (including groupings, etc..). | |
441 | $modcontext = context_module::instance($cm->id); | |
442 | self::validate_context($modcontext); | |
443 | ||
444 | // This require must be here, see mod/forum/discuss.php. | |
445 | require_once($CFG->dirroot . "/mod/forum/lib.php"); | |
446 | ||
447 | // Check they have the view forum capability. | |
448 | require_capability('mod/forum:viewdiscussion', $modcontext, null, true, 'noviewdiscussionspermission', 'forum'); | |
449 | ||
450 | if (! $post = forum_get_post_full($discussion->firstpost)) { | |
451 | throw new moodle_exception('notexists', 'forum'); | |
452 | } | |
453 | ||
454 | // This function check groups, qanda, timed discussions, etc. | |
455 | if (!forum_user_can_see_post($forum, $discussion, $post, null, $cm)) { | |
456 | throw new moodle_exception('noviewdiscussionspermission', 'forum'); | |
457 | } | |
458 | ||
459 | $canviewfullname = has_capability('moodle/site:viewfullnames', $modcontext); | |
460 | ||
461 | // We will add this field in the response. | |
462 | $canreply = forum_user_can_post($forum, $discussion, $USER, $cm, $course, $modcontext); | |
463 | ||
464 | $forumtracked = forum_tp_is_tracked($forum); | |
465 | ||
466 | $sort = 'p.' . $sortby . ' ' . $sortdirection; | |
b1aa7dfa | 467 | $allposts = forum_get_all_discussion_posts($discussion->id, $sort, $forumtracked); |
e2ede426 | 468 | |
b1aa7dfa | 469 | foreach ($allposts as $post) { |
e2ede426 JL |
470 | |
471 | if (!forum_user_can_see_post($forum, $discussion, $post, null, $cm)) { | |
472 | $warning = array(); | |
473 | $warning['item'] = 'post'; | |
474 | $warning['itemid'] = $post->id; | |
475 | $warning['warningcode'] = '1'; | |
476 | $warning['message'] = 'You can\'t see this post'; | |
477 | $warnings[] = $warning; | |
478 | continue; | |
479 | } | |
480 | ||
481 | // Function forum_get_all_discussion_posts adds postread field. | |
f47eeafd JL |
482 | // Note that the value returned can be a boolean or an integer. The WS expects a boolean. |
483 | if (empty($post->postread)) { | |
b1aa7dfa | 484 | $post->postread = false; |
f47eeafd | 485 | } else { |
b1aa7dfa | 486 | $post->postread = true; |
e2ede426 | 487 | } |
f47eeafd | 488 | |
b1aa7dfa JL |
489 | $post->canreply = $canreply; |
490 | if (!empty($post->children)) { | |
491 | $post->children = array_keys($post->children); | |
fb8840d2 | 492 | } else { |
b1aa7dfa | 493 | $post->children = array(); |
e2ede426 JL |
494 | } |
495 | ||
496 | $user = new stdclass(); | |
694bf0c7 | 497 | $user->id = $post->userid; |
e2ede426 | 498 | $user = username_load_fields_from_object($user, $post); |
694bf0c7 | 499 | $post->userfullname = fullname($user, $canviewfullname); |
81f810dc JL |
500 | |
501 | // We can have post written by users that are deleted. In this case, those users don't have a valid context. | |
502 | $usercontext = context_user::instance($user->id, IGNORE_MISSING); | |
503 | if ($usercontext) { | |
504 | $post->userpictureurl = moodle_url::make_webservice_pluginfile_url( | |
505 | $usercontext->id, 'user', 'icon', null, '/', 'f1')->out(false); | |
506 | } else { | |
507 | $post->userpictureurl = ''; | |
508 | } | |
e2ede426 | 509 | |
48fb0250 JL |
510 | // Rewrite embedded images URLs. |
511 | list($post->message, $post->messageformat) = | |
512 | external_format_text($post->message, $post->messageformat, $modcontext->id, 'mod_forum', 'post', $post->id); | |
513 | ||
514 | // List attachments. | |
515 | if (!empty($post->attachment)) { | |
516 | $post->attachments = array(); | |
517 | ||
518 | $fs = get_file_storage(); | |
519 | if ($files = $fs->get_area_files($modcontext->id, 'mod_forum', 'attachment', $post->id, "filename", false)) { | |
520 | foreach ($files as $file) { | |
521 | $filename = $file->get_filename(); | |
da1be050 JL |
522 | $fileurl = moodle_url::make_webservice_pluginfile_url( |
523 | $modcontext->id, 'mod_forum', 'attachment', $post->id, '/', $filename); | |
48fb0250 JL |
524 | |
525 | $post->attachments[] = array( | |
526 | 'filename' => $filename, | |
527 | 'mimetype' => $file->get_mimetype(), | |
da1be050 | 528 | 'fileurl' => $fileurl->out(false) |
48fb0250 JL |
529 | ); |
530 | } | |
531 | } | |
532 | } | |
e2ede426 | 533 | |
b1aa7dfa | 534 | $posts[] = $post; |
e2ede426 JL |
535 | } |
536 | ||
537 | $result = array(); | |
538 | $result['posts'] = $posts; | |
539 | $result['warnings'] = $warnings; | |
540 | return $result; | |
541 | } | |
542 | ||
543 | /** | |
544 | * Describes the get_forum_discussion_posts return value. | |
545 | * | |
546 | * @return external_single_structure | |
547 | * @since Moodle 2.7 | |
548 | */ | |
549 | public static function get_forum_discussion_posts_returns() { | |
550 | return new external_single_structure( | |
551 | array( | |
552 | 'posts' => new external_multiple_structure( | |
553 | new external_single_structure( | |
554 | array( | |
555 | 'id' => new external_value(PARAM_INT, 'Post id'), | |
556 | 'discussion' => new external_value(PARAM_INT, 'Discussion id'), | |
557 | 'parent' => new external_value(PARAM_INT, 'Parent id'), | |
558 | 'userid' => new external_value(PARAM_INT, 'User id'), | |
559 | 'created' => new external_value(PARAM_INT, 'Creation time'), | |
560 | 'modified' => new external_value(PARAM_INT, 'Time modified'), | |
561 | 'mailed' => new external_value(PARAM_INT, 'Mailed?'), | |
562 | 'subject' => new external_value(PARAM_TEXT, 'The post subject'), | |
563 | 'message' => new external_value(PARAM_RAW, 'The post message'), | |
48fb0250 | 564 | 'messageformat' => new external_format_value('message'), |
e2ede426 | 565 | 'messagetrust' => new external_value(PARAM_INT, 'Can we trust?'), |
48fb0250 JL |
566 | 'attachment' => new external_value(PARAM_RAW, 'Has attachments?'), |
567 | 'attachments' => new external_multiple_structure( | |
568 | new external_single_structure( | |
569 | array ( | |
570 | 'filename' => new external_value(PARAM_FILE, 'file name'), | |
571 | 'mimetype' => new external_value(PARAM_RAW, 'mime type'), | |
572 | 'fileurl' => new external_value(PARAM_URL, 'file download url') | |
573 | ) | |
574 | ), 'attachments', VALUE_OPTIONAL | |
575 | ), | |
e2ede426 JL |
576 | 'totalscore' => new external_value(PARAM_INT, 'The post message total score'), |
577 | 'mailnow' => new external_value(PARAM_INT, 'Mail now?'), | |
578 | 'children' => new external_multiple_structure(new external_value(PARAM_INT, 'children post id')), | |
579 | 'canreply' => new external_value(PARAM_BOOL, 'The user can reply to posts?'), | |
580 | 'postread' => new external_value(PARAM_BOOL, 'The post was read'), | |
694bf0c7 JL |
581 | 'userfullname' => new external_value(PARAM_TEXT, 'Post author full name'), |
582 | 'userpictureurl' => new external_value(PARAM_URL, 'Post author picture.', VALUE_OPTIONAL) | |
e2ede426 JL |
583 | ), 'post' |
584 | ) | |
585 | ), | |
586 | 'warnings' => new external_warnings() | |
587 | ) | |
588 | ); | |
589 | } | |
590 | ||
7c51b40a JL |
591 | /** |
592 | * Describes the parameters for get_forum_discussions_paginated. | |
593 | * | |
594 | * @return external_external_function_parameters | |
595 | * @since Moodle 2.8 | |
596 | */ | |
597 | public static function get_forum_discussions_paginated_parameters() { | |
598 | return new external_function_parameters ( | |
599 | array( | |
600 | 'forumid' => new external_value(PARAM_INT, 'forum instance id', VALUE_REQUIRED), | |
601 | 'sortby' => new external_value(PARAM_ALPHA, | |
602 | 'sort by this element: id, timemodified, timestart or timeend', VALUE_DEFAULT, 'timemodified'), | |
603 | 'sortdirection' => new external_value(PARAM_ALPHA, 'sort direction: ASC or DESC', VALUE_DEFAULT, 'DESC'), | |
604 | 'page' => new external_value(PARAM_INT, 'current page', VALUE_DEFAULT, -1), | |
605 | 'perpage' => new external_value(PARAM_INT, 'items per page', VALUE_DEFAULT, 0), | |
606 | ) | |
607 | ); | |
608 | } | |
609 | ||
610 | /** | |
611 | * Returns a list of forum discussions optionally sorted and paginated. | |
612 | * | |
613 | * @param int $forumid the forum instance id | |
614 | * @param string $sortby sort by this element (id, timemodified, timestart or timeend) | |
615 | * @param string $sortdirection sort direction: ASC or DESC | |
616 | * @param int $page page number | |
617 | * @param int $perpage items per page | |
618 | * | |
619 | * @return array the forum discussion details including warnings | |
620 | * @since Moodle 2.8 | |
621 | */ | |
622 | public static function get_forum_discussions_paginated($forumid, $sortby = 'timemodified', $sortdirection = 'DESC', | |
623 | $page = -1, $perpage = 0) { | |
624 | global $CFG, $DB, $USER; | |
625 | ||
626 | require_once($CFG->dirroot . "/mod/forum/lib.php"); | |
627 | ||
628 | $warnings = array(); | |
039c81f0 | 629 | $discussions = array(); |
7c51b40a JL |
630 | |
631 | $params = self::validate_parameters(self::get_forum_discussions_paginated_parameters(), | |
632 | array( | |
633 | 'forumid' => $forumid, | |
634 | 'sortby' => $sortby, | |
635 | 'sortdirection' => $sortdirection, | |
636 | 'page' => $page, | |
637 | 'perpage' => $perpage | |
638 | ) | |
639 | ); | |
640 | ||
641 | // Compact/extract functions are not recommended. | |
642 | $forumid = $params['forumid']; | |
643 | $sortby = $params['sortby']; | |
644 | $sortdirection = $params['sortdirection']; | |
645 | $page = $params['page']; | |
646 | $perpage = $params['perpage']; | |
647 | ||
648 | $sortallowedvalues = array('id', 'timemodified', 'timestart', 'timeend'); | |
649 | if (!in_array($sortby, $sortallowedvalues)) { | |
650 | throw new invalid_parameter_exception('Invalid value for sortby parameter (value: ' . $sortby . '),' . | |
651 | 'allowed values are: ' . implode(',', $sortallowedvalues)); | |
652 | } | |
653 | ||
654 | $sortdirection = strtoupper($sortdirection); | |
655 | $directionallowedvalues = array('ASC', 'DESC'); | |
656 | if (!in_array($sortdirection, $directionallowedvalues)) { | |
657 | throw new invalid_parameter_exception('Invalid value for sortdirection parameter (value: ' . $sortdirection . '),' . | |
658 | 'allowed values are: ' . implode(',', $directionallowedvalues)); | |
659 | } | |
660 | ||
661 | $forum = $DB->get_record('forum', array('id' => $forumid), '*', MUST_EXIST); | |
662 | $course = $DB->get_record('course', array('id' => $forum->course), '*', MUST_EXIST); | |
663 | $cm = get_coursemodule_from_instance('forum', $forum->id, $course->id, false, MUST_EXIST); | |
664 | ||
665 | // Validate the module context. It checks everything that affects the module visibility (including groupings, etc..). | |
666 | $modcontext = context_module::instance($cm->id); | |
667 | self::validate_context($modcontext); | |
668 | ||
669 | // Check they have the view forum capability. | |
670 | require_capability('mod/forum:viewdiscussion', $modcontext, null, true, 'noviewdiscussionspermission', 'forum'); | |
671 | ||
672 | $sort = 'd.' . $sortby . ' ' . $sortdirection; | |
039c81f0 | 673 | $alldiscussions = forum_get_discussions($cm, $sort, true, -1, -1, true, $page, $perpage); |
7c51b40a | 674 | |
039c81f0 | 675 | if ($alldiscussions) { |
7c51b40a JL |
676 | $canviewfullname = has_capability('moodle/site:viewfullnames', $modcontext); |
677 | ||
678 | // Get the unreads array, this takes a forum id and returns data for all discussions. | |
679 | $unreads = array(); | |
680 | if ($cantrack = forum_tp_can_track_forums($forum)) { | |
681 | if ($forumtracked = forum_tp_is_tracked($forum)) { | |
682 | $unreads = forum_get_discussions_unread($cm); | |
683 | } | |
684 | } | |
685 | // The forum function returns the replies for all the discussions in a given forum. | |
686 | $replies = forum_count_discussion_replies($forumid, $sort, -1, $page, $perpage); | |
687 | ||
039c81f0 JL |
688 | foreach ($alldiscussions as $discussion) { |
689 | ||
7c51b40a | 690 | // This function checks for qanda forums. |
039c81f0 JL |
691 | // Note that the forum_get_discussions returns as id the post id, not the discussion id so we need to do this. |
692 | $discussionrec = clone $discussion; | |
693 | $discussionrec->id = $discussion->discussion; | |
694 | if (!forum_user_can_see_discussion($forum, $discussionrec, $modcontext)) { | |
7c51b40a JL |
695 | $warning = array(); |
696 | // Function forum_get_discussions returns forum_posts ids not forum_discussions ones. | |
697 | $warning['item'] = 'post'; | |
698 | $warning['itemid'] = $discussion->id; | |
699 | $warning['warningcode'] = '1'; | |
700 | $warning['message'] = 'You can\'t see this discussion'; | |
701 | $warnings[] = $warning; | |
702 | continue; | |
703 | } | |
704 | ||
705 | $discussion->numunread = 0; | |
706 | if ($cantrack && $forumtracked) { | |
707 | if (isset($unreads[$discussion->discussion])) { | |
708 | $discussion->numunread = (int) $unreads[$discussion->discussion]; | |
709 | } | |
710 | } | |
711 | ||
712 | $discussion->numreplies = 0; | |
713 | if (!empty($replies[$discussion->discussion])) { | |
714 | $discussion->numreplies = (int) $replies[$discussion->discussion]->replies; | |
715 | } | |
716 | ||
717 | // Load user objects from the results of the query. | |
718 | $user = new stdclass(); | |
719 | $user->id = $discussion->userid; | |
720 | $user = username_load_fields_from_object($user, $discussion); | |
721 | $discussion->userfullname = fullname($user, $canviewfullname); | |
81f810dc JL |
722 | |
723 | // We can have post written by users that are deleted. In this case, those users don't have a valid context. | |
724 | $usercontext = context_user::instance($user->id, IGNORE_MISSING); | |
725 | if ($usercontext) { | |
726 | $discussion->userpictureurl = moodle_url::make_webservice_pluginfile_url( | |
727 | $usercontext->id, 'user', 'icon', null, '/', 'f1')->out(false); | |
728 | } else { | |
729 | $discussion->userpictureurl = ''; | |
730 | } | |
7c51b40a JL |
731 | |
732 | $usermodified = new stdclass(); | |
733 | $usermodified->id = $discussion->usermodified; | |
734 | $usermodified = username_load_fields_from_object($usermodified, $discussion, 'um'); | |
735 | $discussion->usermodifiedfullname = fullname($usermodified, $canviewfullname); | |
81f810dc JL |
736 | |
737 | // We can have post written by users that are deleted. In this case, those users don't have a valid context. | |
738 | $usercontext = context_user::instance($usermodified->id, IGNORE_MISSING); | |
739 | if ($usercontext) { | |
740 | $discussion->usermodifiedpictureurl = moodle_url::make_webservice_pluginfile_url( | |
741 | $usercontext->id, 'user', 'icon', null, '/', 'f1')->out(false); | |
742 | } else { | |
743 | $discussion->usermodifiedpictureurl = ''; | |
744 | } | |
7c51b40a JL |
745 | |
746 | // Rewrite embedded images URLs. | |
747 | list($discussion->message, $discussion->messageformat) = | |
748 | external_format_text($discussion->message, $discussion->messageformat, | |
749 | $modcontext->id, 'mod_forum', 'post', $discussion->id); | |
750 | ||
751 | // List attachments. | |
752 | if (!empty($discussion->attachment)) { | |
753 | $discussion->attachments = array(); | |
754 | ||
755 | $fs = get_file_storage(); | |
756 | if ($files = $fs->get_area_files($modcontext->id, 'mod_forum', 'attachment', | |
757 | $discussion->id, "filename", false)) { | |
758 | foreach ($files as $file) { | |
759 | $filename = $file->get_filename(); | |
760 | ||
761 | $discussion->attachments[] = array( | |
762 | 'filename' => $filename, | |
763 | 'mimetype' => $file->get_mimetype(), | |
764 | 'fileurl' => file_encode_url($CFG->wwwroot.'/webservice/pluginfile.php', | |
765 | '/'.$modcontext->id.'/mod_forum/attachment/'.$discussion->id.'/'.$filename) | |
766 | ); | |
767 | } | |
768 | } | |
769 | } | |
770 | ||
039c81f0 | 771 | $discussions[] = $discussion; |
7c51b40a JL |
772 | } |
773 | } | |
774 | ||
775 | $result = array(); | |
776 | $result['discussions'] = $discussions; | |
777 | $result['warnings'] = $warnings; | |
778 | return $result; | |
779 | ||
780 | } | |
781 | ||
782 | /** | |
783 | * Describes the get_forum_discussions_paginated return value. | |
784 | * | |
785 | * @return external_single_structure | |
786 | * @since Moodle 2.8 | |
787 | */ | |
788 | public static function get_forum_discussions_paginated_returns() { | |
789 | return new external_single_structure( | |
790 | array( | |
791 | 'discussions' => new external_multiple_structure( | |
792 | new external_single_structure( | |
793 | array( | |
794 | 'id' => new external_value(PARAM_INT, 'Post id'), | |
795 | 'name' => new external_value(PARAM_TEXT, 'Discussion name'), | |
796 | 'groupid' => new external_value(PARAM_INT, 'Group id'), | |
797 | 'timemodified' => new external_value(PARAM_INT, 'Time modified'), | |
798 | 'usermodified' => new external_value(PARAM_INT, 'The id of the user who last modified'), | |
799 | 'timestart' => new external_value(PARAM_INT, 'Time discussion can start'), | |
800 | 'timeend' => new external_value(PARAM_INT, 'Time discussion ends'), | |
801 | 'discussion' => new external_value(PARAM_INT, 'Discussion id'), | |
802 | 'parent' => new external_value(PARAM_INT, 'Parent id'), | |
803 | 'userid' => new external_value(PARAM_INT, 'User who started the discussion id'), | |
804 | 'created' => new external_value(PARAM_INT, 'Creation time'), | |
805 | 'modified' => new external_value(PARAM_INT, 'Time modified'), | |
806 | 'mailed' => new external_value(PARAM_INT, 'Mailed?'), | |
807 | 'subject' => new external_value(PARAM_TEXT, 'The post subject'), | |
808 | 'message' => new external_value(PARAM_RAW, 'The post message'), | |
809 | 'messageformat' => new external_format_value('message'), | |
810 | 'messagetrust' => new external_value(PARAM_INT, 'Can we trust?'), | |
811 | 'attachment' => new external_value(PARAM_RAW, 'Has attachments?'), | |
812 | 'attachments' => new external_multiple_structure( | |
813 | new external_single_structure( | |
814 | array ( | |
815 | 'filename' => new external_value(PARAM_FILE, 'file name'), | |
816 | 'mimetype' => new external_value(PARAM_RAW, 'mime type'), | |
817 | 'fileurl' => new external_value(PARAM_URL, 'file download url') | |
818 | ) | |
819 | ), 'attachments', VALUE_OPTIONAL | |
820 | ), | |
821 | 'totalscore' => new external_value(PARAM_INT, 'The post message total score'), | |
822 | 'mailnow' => new external_value(PARAM_INT, 'Mail now?'), | |
823 | 'userfullname' => new external_value(PARAM_TEXT, 'Post author full name'), | |
824 | 'usermodifiedfullname' => new external_value(PARAM_TEXT, 'Post modifier full name'), | |
825 | 'userpictureurl' => new external_value(PARAM_URL, 'Post author picture.'), | |
826 | 'usermodifiedpictureurl' => new external_value(PARAM_URL, 'Post modifier picture.'), | |
827 | 'numreplies' => new external_value(PARAM_TEXT, 'The number of replies in the discussion'), | |
828 | 'numunread' => new external_value(PARAM_INT, 'The number of unread discussions.') | |
829 | ), 'post' | |
830 | ) | |
831 | ), | |
832 | 'warnings' => new external_warnings() | |
833 | ) | |
834 | ); | |
835 | } | |
836 | ||
4a1e44a1 JL |
837 | /** |
838 | * Returns description of method parameters | |
839 | * | |
840 | * @return external_function_parameters | |
841 | * @since Moodle 2.9 | |
842 | */ | |
843 | public static function view_forum_parameters() { | |
844 | return new external_function_parameters( | |
845 | array( | |
846 | 'forumid' => new external_value(PARAM_INT, 'forum instance id') | |
847 | ) | |
848 | ); | |
849 | } | |
850 | ||
851 | /** | |
1c2b7882 | 852 | * Trigger the course module viewed event and update the module completion status. |
4a1e44a1 JL |
853 | * |
854 | * @param int $forumid the forum instance id | |
855 | * @return array of warnings and status result | |
856 | * @since Moodle 2.9 | |
857 | * @throws moodle_exception | |
858 | */ | |
859 | public static function view_forum($forumid) { | |
860 | global $DB, $CFG; | |
861 | require_once($CFG->dirroot . "/mod/forum/lib.php"); | |
862 | ||
863 | $params = self::validate_parameters(self::view_forum_parameters(), | |
864 | array( | |
865 | 'forumid' => $forumid | |
866 | )); | |
867 | $warnings = array(); | |
868 | ||
869 | // Request and permission validation. | |
870 | $forum = $DB->get_record('forum', array('id' => $params['forumid']), 'id', MUST_EXIST); | |
871 | list($course, $cm) = get_course_and_cm_from_instance($forum, 'forum'); | |
872 | ||
873 | $context = context_module::instance($cm->id); | |
874 | self::validate_context($context); | |
875 | ||
ea2fa324 JL |
876 | require_capability('mod/forum:viewdiscussion', $context, null, true, 'noviewdiscussionspermission', 'forum'); |
877 | ||
4a1e44a1 JL |
878 | // Call the forum/lib API. |
879 | forum_view($forum, $course, $cm, $context); | |
880 | ||
881 | $result = array(); | |
882 | $result['status'] = true; | |
883 | $result['warnings'] = $warnings; | |
884 | return $result; | |
885 | } | |
886 | ||
887 | /** | |
888 | * Returns description of method result value | |
889 | * | |
890 | * @return external_description | |
891 | * @since Moodle 2.9 | |
892 | */ | |
893 | public static function view_forum_returns() { | |
894 | return new external_single_structure( | |
895 | array( | |
896 | 'status' => new external_value(PARAM_BOOL, 'status: true if success'), | |
897 | 'warnings' => new external_warnings() | |
898 | ) | |
899 | ); | |
900 | } | |
901 | ||
a3c315dd JL |
902 | /** |
903 | * Returns description of method parameters | |
904 | * | |
905 | * @return external_function_parameters | |
906 | * @since Moodle 2.9 | |
907 | */ | |
908 | public static function view_forum_discussion_parameters() { | |
909 | return new external_function_parameters( | |
910 | array( | |
911 | 'discussionid' => new external_value(PARAM_INT, 'discussion id') | |
912 | ) | |
913 | ); | |
914 | } | |
915 | ||
916 | /** | |
1c2b7882 | 917 | * Trigger the discussion viewed event. |
a3c315dd JL |
918 | * |
919 | * @param int $discussionid the discussion id | |
920 | * @return array of warnings and status result | |
921 | * @since Moodle 2.9 | |
922 | * @throws moodle_exception | |
923 | */ | |
924 | public static function view_forum_discussion($discussionid) { | |
925 | global $DB, $CFG; | |
926 | require_once($CFG->dirroot . "/mod/forum/lib.php"); | |
927 | ||
928 | $params = self::validate_parameters(self::view_forum_discussion_parameters(), | |
929 | array( | |
930 | 'discussionid' => $discussionid | |
931 | )); | |
932 | $warnings = array(); | |
933 | ||
934 | $discussion = $DB->get_record('forum_discussions', array('id' => $params['discussionid']), '*', MUST_EXIST); | |
935 | $forum = $DB->get_record('forum', array('id' => $discussion->forum), '*', MUST_EXIST); | |
936 | list($course, $cm) = get_course_and_cm_from_instance($forum, 'forum'); | |
937 | ||
938 | // Validate the module context. It checks everything that affects the module visibility (including groupings, etc..). | |
939 | $modcontext = context_module::instance($cm->id); | |
940 | self::validate_context($modcontext); | |
941 | ||
ea2fa324 JL |
942 | require_capability('mod/forum:viewdiscussion', $modcontext, null, true, 'noviewdiscussionspermission', 'forum'); |
943 | ||
a3c315dd JL |
944 | // Call the forum/lib API. |
945 | forum_discussion_view($modcontext, $forum, $discussion); | |
946 | ||
947 | $result = array(); | |
948 | $result['status'] = true; | |
949 | $result['warnings'] = $warnings; | |
950 | return $result; | |
951 | } | |
952 | ||
953 | /** | |
954 | * Returns description of method result value | |
955 | * | |
956 | * @return external_description | |
957 | * @since Moodle 2.9 | |
958 | */ | |
959 | public static function view_forum_discussion_returns() { | |
960 | return new external_single_structure( | |
961 | array( | |
962 | 'status' => new external_value(PARAM_BOOL, 'status: true if success'), | |
963 | 'warnings' => new external_warnings() | |
964 | ) | |
965 | ); | |
966 | } | |
967 | ||
50a20317 JL |
968 | /** |
969 | * Returns description of method parameters | |
970 | * | |
971 | * @return external_function_parameters | |
972 | * @since Moodle 3.0 | |
973 | */ | |
974 | public static function add_discussion_post_parameters() { | |
975 | return new external_function_parameters( | |
976 | array( | |
977 | 'postid' => new external_value(PARAM_INT, 'the post id we are going to reply to | |
978 | (can be the initial discussion post'), | |
979 | 'subject' => new external_value(PARAM_TEXT, 'new post subject'), | |
980 | 'message' => new external_value(PARAM_RAW, 'new post message (only html format allowed)'), | |
981 | 'options' => new external_multiple_structure ( | |
982 | new external_single_structure( | |
983 | array( | |
984 | 'name' => new external_value(PARAM_ALPHANUM, | |
985 | 'The allowed keys (value format) are: | |
986 | discussionsubscribe (bool); subscribe to the discussion?, default to true | |
987 | '), | |
988 | 'value' => new external_value(PARAM_RAW, 'the value of the option, | |
989 | this param is validated in the external function.' | |
990 | ) | |
991 | ) | |
992 | ), 'Options', VALUE_DEFAULT, array()) | |
993 | ) | |
994 | ); | |
995 | } | |
996 | ||
997 | /** | |
998 | * Create new posts into an existing discussion. | |
999 | * | |
1000 | * @param int $postid the post id we are going to reply to | |
1001 | * @param string $subject new post subject | |
1002 | * @param string $message new post message (only html format allowed) | |
1003 | * @param array $options optional settings | |
1004 | * @return array of warnings and the new post id | |
1005 | * @since Moodle 3.0 | |
1006 | * @throws moodle_exception | |
1007 | */ | |
1008 | public static function add_discussion_post($postid, $subject, $message, $options = array()) { | |
1009 | global $DB, $CFG, $USER; | |
1010 | require_once($CFG->dirroot . "/mod/forum/lib.php"); | |
1011 | ||
1012 | $params = self::validate_parameters(self::add_discussion_post_parameters(), | |
1013 | array( | |
1014 | 'postid' => $postid, | |
1015 | 'subject' => $subject, | |
1016 | 'message' => $message, | |
1017 | 'options' => $options | |
1018 | )); | |
1019 | // Validate options. | |
1020 | $options = array( | |
1021 | 'discussionsubscribe' => true | |
1022 | ); | |
1023 | foreach ($params['options'] as $option) { | |
1024 | $name = trim($option['name']); | |
1025 | switch ($name) { | |
1026 | case 'discussionsubscribe': | |
1027 | $value = clean_param($option['value'], PARAM_BOOL); | |
1028 | break; | |
1029 | default: | |
1030 | throw new moodle_exception('errorinvalidparam', 'webservice', '', $name); | |
1031 | } | |
1032 | $options[$name] = $value; | |
1033 | } | |
1034 | ||
1035 | $warnings = array(); | |
1036 | ||
1037 | if (! $parent = forum_get_post_full($params['postid'])) { | |
1038 | throw new moodle_exception('invalidparentpostid', 'forum'); | |
1039 | } | |
1040 | ||
1041 | if (! $discussion = $DB->get_record("forum_discussions", array("id" => $parent->discussion))) { | |
1042 | throw new moodle_exception('notpartofdiscussion', 'forum'); | |
1043 | } | |
1044 | ||
1045 | // Request and permission validation. | |
1046 | $forum = $DB->get_record('forum', array('id' => $discussion->forum), '*', MUST_EXIST); | |
1047 | list($course, $cm) = get_course_and_cm_from_instance($forum, 'forum'); | |
1048 | ||
1049 | $context = context_module::instance($cm->id); | |
1050 | self::validate_context($context); | |
1051 | ||
1052 | if (!forum_user_can_post($forum, $discussion, $USER, $cm, $course, $context)) { | |
1053 | throw new moodle_exception('nopostforum', 'forum'); | |
1054 | } | |
1055 | ||
1056 | $thresholdwarning = forum_check_throttling($forum, $cm); | |
1057 | forum_check_blocking_threshold($thresholdwarning); | |
1058 | ||
1059 | // Create the post. | |
1060 | $post = new stdClass(); | |
1061 | $post->discussion = $discussion->id; | |
1062 | $post->parent = $parent->id; | |
1063 | $post->subject = $params['subject']; | |
1064 | $post->message = $params['message']; | |
1065 | $post->messageformat = FORMAT_HTML; // Force formatting for now. | |
1066 | $post->messagetrust = trusttext_trusted($context); | |
1067 | $post->itemid = 0; | |
1068 | ||
1069 | if ($postid = forum_add_new_post($post, null)) { | |
1070 | ||
1071 | $post->id = $postid; | |
1072 | ||
1073 | // Trigger events and completion. | |
1074 | $params = array( | |
1075 | 'context' => $context, | |
1076 | 'objectid' => $post->id, | |
1077 | 'other' => array( | |
1078 | 'discussionid' => $discussion->id, | |
1079 | 'forumid' => $forum->id, | |
1080 | 'forumtype' => $forum->type, | |
1081 | ) | |
1082 | ); | |
1083 | $event = \mod_forum\event\post_created::create($params); | |
1084 | $event->add_record_snapshot('forum_posts', $post); | |
1085 | $event->add_record_snapshot('forum_discussions', $discussion); | |
1086 | $event->trigger(); | |
1087 | ||
1088 | // Update completion state. | |
1089 | $completion = new completion_info($course); | |
1090 | if ($completion->is_enabled($cm) && | |
1091 | ($forum->completionreplies || $forum->completionposts)) { | |
1092 | $completion->update_state($cm, COMPLETION_COMPLETE); | |
1093 | } | |
1094 | ||
1095 | $settings = new stdClass(); | |
1096 | $settings->discussionsubscribe = $options['discussionsubscribe']; | |
1097 | forum_post_subscription($settings, $forum, $discussion); | |
1098 | } else { | |
1099 | throw new moodle_exception('couldnotadd', 'forum'); | |
1100 | } | |
1101 | ||
1102 | $result = array(); | |
1103 | $result['postid'] = $postid; | |
1104 | $result['warnings'] = $warnings; | |
1105 | return $result; | |
1106 | } | |
1107 | ||
1108 | /** | |
1109 | * Returns description of method result value | |
1110 | * | |
1111 | * @return external_description | |
1112 | * @since Moodle 3.0 | |
1113 | */ | |
1114 | public static function add_discussion_post_returns() { | |
1115 | return new external_single_structure( | |
1116 | array( | |
1117 | 'postid' => new external_value(PARAM_INT, 'new post id'), | |
1118 | 'warnings' => new external_warnings() | |
1119 | ) | |
1120 | ); | |
1121 | } | |
1122 | ||
2b9fe87d | 1123 | } |