weekly release 3.0dev
[moodle.git] / mod / forum / tests / externallib_test.php
CommitLineData
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 * The module forums external functions unit tests
20 *
21 * @package mod_forum
22 * @category external
23 * @copyright 2012 Mark Nelson <markn@moodle.com>
24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 */
26
27defined('MOODLE_INTERNAL') || die();
28
29global $CFG;
30
31require_once($CFG->dirroot . '/webservice/tests/helpers.php');
32
33class mod_forum_external_testcase extends externallib_advanced_testcase {
34
35 /**
36 * Tests set up
37 */
38 protected function setUp() {
39 global $CFG;
40
59075a43
AN
41 // We must clear the subscription caches. This has to be done both before each test, and after in case of other
42 // tests using these functions.
43 \mod_forum\subscriptions::reset_forum_cache();
44
2b9fe87d
MN
45 require_once($CFG->dirroot . '/mod/forum/externallib.php');
46 }
47
59075a43
AN
48 public function tearDown() {
49 // We must clear the subscription caches. This has to be done both before each test, and after in case of other
50 // tests using these functions.
51 \mod_forum\subscriptions::reset_forum_cache();
52 }
53
2b9fe87d
MN
54 /**
55 * Test get forums
56 */
57 public function test_mod_forum_get_forums_by_courses() {
58 global $USER, $CFG, $DB;
59
60 $this->resetAfterTest(true);
61
62 // Create a user.
63 $user = self::getDataGenerator()->create_user();
64
65 // Set to the user.
66 self::setUser($user);
67
68 // Create courses to add the modules.
69 $course1 = self::getDataGenerator()->create_course();
70 $course2 = self::getDataGenerator()->create_course();
71
72 // First forum.
73 $record = new stdClass();
74 $record->introformat = FORMAT_HTML;
75 $record->course = $course1->id;
76 $forum1 = self::getDataGenerator()->create_module('forum', $record);
77
78 // Second forum.
79 $record = new stdClass();
80 $record->introformat = FORMAT_HTML;
81 $record->course = $course2->id;
82 $forum2 = self::getDataGenerator()->create_module('forum', $record);
83
7ea6ada3
JL
84 // Add discussions to the forums.
85 $record = new stdClass();
86 $record->course = $course1->id;
87 $record->userid = $user->id;
88 $record->forum = $forum1->id;
89 $discussion1 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
90 // Expect one discussion.
91 $forum1->numdiscussions = 1;
92
93 $record = new stdClass();
94 $record->course = $course2->id;
95 $record->userid = $user->id;
96 $record->forum = $forum2->id;
97 $discussion2 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
98 $discussion3 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
99 // Expect two discussions.
100 $forum2->numdiscussions = 2;
101
2b9fe87d
MN
102 // Check the forum was correctly created.
103 $this->assertEquals(2, $DB->count_records_select('forum', 'id = :forum1 OR id = :forum2',
104 array('forum1' => $forum1->id, 'forum2' => $forum2->id)));
105
106 // Enrol the user in two courses.
909f27ac
JM
107 // DataGenerator->enrol_user automatically sets a role for the user with the permission mod/form:viewdiscussion.
108 $this->getDataGenerator()->enrol_user($user->id, $course1->id, null, 'manual');
109 // Execute real Moodle enrolment as we'll call unenrol() method on the instance later.
2b9fe87d 110 $enrol = enrol_get_plugin('manual');
2b9fe87d
MN
111 $enrolinstances = enrol_get_instances($course2->id, true);
112 foreach ($enrolinstances as $courseenrolinstance) {
113 if ($courseenrolinstance->enrol == "manual") {
114 $instance2 = $courseenrolinstance;
115 break;
116 }
117 }
118 $enrol->enrol_user($instance2, $user->id);
119
2b9fe87d 120 // Assign capabilities to view forums for forum 2.
74b63eae 121 $cm2 = get_coursemodule_from_id('forum', $forum2->cmid, 0, false, MUST_EXIST);
2b9fe87d
MN
122 $context2 = context_module::instance($cm2->id);
123 $newrole = create_role('Role 2', 'role2', 'Role 2 description');
124 $roleid2 = $this->assignUserCapability('mod/forum:viewdiscussion', $context2->id, $newrole);
125
126 // Create what we expect to be returned when querying the two courses.
c8f1d8a0
JL
127 unset($forum1->displaywordcount);
128 unset($forum2->displaywordcount);
129
2b9fe87d
MN
130 $expectedforums = array();
131 $expectedforums[$forum1->id] = (array) $forum1;
132 $expectedforums[$forum2->id] = (array) $forum2;
133
134 // Call the external function passing course ids.
135 $forums = mod_forum_external::get_forums_by_courses(array($course1->id, $course2->id));
c8f1d8a0
JL
136 $forums = external_api::clean_returnvalue(mod_forum_external::get_forums_by_courses_returns(), $forums);
137 $this->assertCount(2, $forums);
138 foreach ($forums as $forum) {
139 $this->assertEquals($expectedforums[$forum['id']], $forum);
140 }
2b9fe87d
MN
141
142 // Call the external function without passing course id.
143 $forums = mod_forum_external::get_forums_by_courses();
c8f1d8a0
JL
144 $forums = external_api::clean_returnvalue(mod_forum_external::get_forums_by_courses_returns(), $forums);
145 $this->assertCount(2, $forums);
146 foreach ($forums as $forum) {
147 $this->assertEquals($expectedforums[$forum['id']], $forum);
148 }
2b9fe87d
MN
149
150 // Unenrol user from second course and alter expected forums.
151 $enrol->unenrol_user($instance2, $user->id);
152 unset($expectedforums[$forum2->id]);
153
154 // Call the external function without passing course id.
155 $forums = mod_forum_external::get_forums_by_courses();
c8f1d8a0
JL
156 $forums = external_api::clean_returnvalue(mod_forum_external::get_forums_by_courses_returns(), $forums);
157 $this->assertCount(1, $forums);
158 $this->assertEquals($expectedforums[$forum1->id], $forums[0]);
159
160 // Call for the second course we unenrolled the user from.
161 $forums = mod_forum_external::get_forums_by_courses(array($course2->id));
162 $forums = external_api::clean_returnvalue(mod_forum_external::get_forums_by_courses_returns(), $forums);
163 $this->assertCount(0, $forums);
a9a0cb69
MN
164 }
165
166 /**
167 * Test get forum discussions
168 */
169 public function test_mod_forum_get_forum_discussions() {
170 global $USER, $CFG, $DB;
171
172 $this->resetAfterTest(true);
173
174 // Set the CFG variable to allow track forums.
175 $CFG->forum_trackreadposts = true;
176
177 // Create a user who can track forums.
178 $record = new stdClass();
179 $record->trackforums = true;
180 $user1 = self::getDataGenerator()->create_user($record);
181 // Create a bunch of other users to post.
182 $user2 = self::getDataGenerator()->create_user();
183 $user3 = self::getDataGenerator()->create_user();
184 $user4 = self::getDataGenerator()->create_user();
185
186 // Set the first created user to the test user.
187 self::setUser($user1);
188
189 // Create courses to add the modules.
190 $course1 = self::getDataGenerator()->create_course();
191 $course2 = self::getDataGenerator()->create_course();
192
193 // First forum with tracking off.
194 $record = new stdClass();
195 $record->course = $course1->id;
196 $record->trackingtype = FORUM_TRACKING_OFF;
197 $forum1 = self::getDataGenerator()->create_module('forum', $record);
198
199 // Second forum of type 'qanda' with tracking enabled.
200 $record = new stdClass();
201 $record->course = $course2->id;
202 $record->type = 'qanda';
bd8f5d45 203 $record->trackingtype = FORUM_TRACKING_FORCED;
a9a0cb69
MN
204 $forum2 = self::getDataGenerator()->create_module('forum', $record);
205
a9a0cb69
MN
206 // Add discussions to the forums.
207 $record = new stdClass();
208 $record->course = $course1->id;
209 $record->userid = $user1->id;
210 $record->forum = $forum1->id;
c3f31a3d 211 $discussion1 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
a9a0cb69
MN
212
213 $record = new stdClass();
214 $record->course = $course2->id;
215 $record->userid = $user2->id;
216 $record->forum = $forum2->id;
c3f31a3d 217 $discussion2 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
a9a0cb69 218
a9a0cb69
MN
219 // Add three replies to the discussion 1 from different users.
220 $record = new stdClass();
221 $record->discussion = $discussion1->id;
222 $record->parent = $discussion1->firstpost;
223 $record->userid = $user2->id;
c3f31a3d 224 $discussion1reply1 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_post($record);
2b9fe87d 225
a9a0cb69
MN
226 $record->parent = $discussion1reply1->id;
227 $record->userid = $user3->id;
c3f31a3d 228 $discussion1reply2 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_post($record);
a9a0cb69
MN
229
230 $record->userid = $user4->id;
c3f31a3d 231 $discussion1reply3 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_post($record);
a9a0cb69
MN
232
233 // Add two replies to discussion 2 from different users.
234 $record = new stdClass();
235 $record->discussion = $discussion2->id;
236 $record->parent = $discussion2->firstpost;
237 $record->userid = $user1->id;
c3f31a3d 238 $discussion2reply1 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_post($record);
a9a0cb69
MN
239
240 $record->parent = $discussion2reply1->id;
241 $record->userid = $user3->id;
c3f31a3d 242 $discussion2reply2 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_post($record);
a9a0cb69
MN
243
244 // Check the forums were correctly created.
40afeb40
JL
245 $this->assertEquals(2, $DB->count_records_select('forum', 'id = :forum1 OR id = :forum2',
246 array('forum1' => $forum1->id, 'forum2' => $forum2->id)));
a9a0cb69
MN
247
248 // Check the discussions were correctly created.
40afeb40
JL
249 $this->assertEquals(2, $DB->count_records_select('forum_discussions', 'forum = :forum1 OR forum = :forum2',
250 array('forum1' => $forum1->id, 'forum2' => $forum2->id)));
a9a0cb69
MN
251
252 // Check the posts were correctly created, don't forget each discussion created also creates a post.
253 $this->assertEquals(7, $DB->count_records_select('forum_posts', 'discussion = :discussion1 OR discussion = :discussion2',
254 array('discussion1' => $discussion1->id, 'discussion2' => $discussion2->id)));
255
256 // Enrol the user in the first course.
257 $enrol = enrol_get_plugin('manual');
909f27ac
JM
258 // Following line enrol and assign default role id to the user.
259 // So the user automatically gets mod/forum:viewdiscussion on all forums of the course.
260 $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
a9a0cb69
MN
261
262 // Now enrol into the second course.
909f27ac 263 // We don't use the dataGenerator as we need to get the $instance2 to unenrol later.
a9a0cb69
MN
264 $enrolinstances = enrol_get_instances($course2->id, true);
265 foreach ($enrolinstances as $courseenrolinstance) {
266 if ($courseenrolinstance->enrol == "manual") {
267 $instance2 = $courseenrolinstance;
268 break;
269 }
270 }
271 $enrol->enrol_user($instance2, $user1->id);
272
a9a0cb69 273 // Assign capabilities to view discussions for forum 2.
74b63eae 274 $cm = get_coursemodule_from_id('forum', $forum2->cmid, 0, false, MUST_EXIST);
a9a0cb69
MN
275 $context = context_module::instance($cm->id);
276 $newrole = create_role('Role 2', 'role2', 'Role 2 description');
277 $this->assignUserCapability('mod/forum:viewdiscussion', $context->id, $newrole);
278
a9a0cb69
MN
279 // Create what we expect to be returned when querying the forums.
280 $expecteddiscussions = array();
9a3f7a48 281 $expecteddiscussions[] = array(
a9a0cb69
MN
282 'id' => $discussion1->id,
283 'course' => $discussion1->course,
284 'forum' => $discussion1->forum,
285 'name' => $discussion1->name,
286 'firstpost' => $discussion1->firstpost,
287 'userid' => $discussion1->userid,
288 'groupid' => $discussion1->groupid,
289 'assessed' => $discussion1->assessed,
290 'timemodified' => $discussion1reply3->created,
291 'usermodified' => $discussion1reply3->userid,
292 'timestart' => $discussion1->timestart,
293 'timeend' => $discussion1->timeend,
294 'firstuserfullname' => fullname($user1),
295 'firstuserimagealt' => $user1->imagealt,
296 'firstuserpicture' => $user1->picture,
297 'firstuseremail' => $user1->email,
298 'subject' => $discussion1->name,
299 'numreplies' => 3,
300 'numunread' => '',
301 'lastpost' => $discussion1reply3->id,
302 'lastuserid' => $user4->id,
303 'lastuserfullname' => fullname($user4),
304 'lastuserimagealt' => $user4->imagealt,
305 'lastuserpicture' => $user4->picture,
306 'lastuseremail' => $user4->email
307 );
9a3f7a48 308 $expecteddiscussions[] = array(
a9a0cb69
MN
309 'id' => $discussion2->id,
310 'course' => $discussion2->course,
311 'forum' => $discussion2->forum,
312 'name' => $discussion2->name,
313 'firstpost' => $discussion2->firstpost,
314 'userid' => $discussion2->userid,
315 'groupid' => $discussion2->groupid,
316 'assessed' => $discussion2->assessed,
317 'timemodified' => $discussion2reply2->created,
318 'usermodified' => $discussion2reply2->userid,
319 'timestart' => $discussion2->timestart,
320 'timeend' => $discussion2->timeend,
321 'firstuserfullname' => fullname($user2),
322 'firstuserimagealt' => $user2->imagealt,
323 'firstuserpicture' => $user2->picture,
324 'firstuseremail' => $user2->email,
325 'subject' => $discussion2->name,
326 'numreplies' => 2,
327 'numunread' => 3,
328 'lastpost' => $discussion2reply2->id,
329 'lastuserid' => $user3->id,
330 'lastuserfullname' => fullname($user3),
331 'lastuserimagealt' => $user3->imagealt,
332 'lastuserpicture' => $user3->picture,
333 'lastuseremail' => $user3->email
334 );
a9a0cb69
MN
335
336 // Call the external function passing forum ids.
40afeb40 337 $discussions = mod_forum_external::get_forum_discussions(array($forum1->id, $forum2->id));
9a3f7a48 338 $discussions = external_api::clean_returnvalue(mod_forum_external::get_forum_discussions_returns(), $discussions);
a9a0cb69 339 $this->assertEquals($expecteddiscussions, $discussions);
40afeb40
JL
340 // Some debugging is going to be produced, this is because we switch PAGE contexts in the get_forum_discussions function,
341 // the switch happens when the validate_context function is called inside a foreach loop.
342 // See MDL-41746 for more information.
343 $this->assertDebuggingCalled();
a9a0cb69
MN
344
345 // Remove the users post from the qanda forum and ensure they can not return the discussion.
346 $DB->delete_records('forum_posts', array('id' => $discussion2reply1->id));
40afeb40
JL
347 $discussions = mod_forum_external::get_forum_discussions(array($forum2->id));
348 $discussions = external_api::clean_returnvalue(mod_forum_external::get_forum_discussions_returns(), $discussions);
349 $this->assertEquals(0, count($discussions));
a9a0cb69
MN
350
351 // Call without required view discussion capability.
909f27ac 352 $this->unassignUserCapability('mod/forum:viewdiscussion', null, null, $course1->id);
a9a0cb69
MN
353 try {
354 mod_forum_external::get_forum_discussions(array($forum1->id));
355 $this->fail('Exception expected due to missing capability.');
356 } catch (moodle_exception $e) {
357 $this->assertEquals('nopermissions', $e->errorcode);
358 }
40afeb40 359 $this->assertDebuggingCalled();
a9a0cb69
MN
360
361 // Unenrol user from second course.
362 $enrol->unenrol_user($instance2, $user1->id);
363
364 // Call for the second course we unenrolled the user from, make sure exception thrown.
365 try {
366 mod_forum_external::get_forum_discussions(array($forum2->id));
367 $this->fail('Exception expected due to being unenrolled from the course.');
368 } catch (moodle_exception $e) {
369 $this->assertEquals('requireloginerror', $e->errorcode);
370 }
2b9fe87d 371 }
e2ede426
JL
372
373 /**
374 * Test get forum posts
375 */
376 public function test_mod_forum_get_forum_discussion_posts() {
377 global $CFG;
378
379 $this->resetAfterTest(true);
380
381 // Set the CFG variable to allow track forums.
382 $CFG->forum_trackreadposts = true;
383
384 // Create a user who can track forums.
385 $record = new stdClass();
386 $record->trackforums = true;
387 $user1 = self::getDataGenerator()->create_user($record);
388 // Create a bunch of other users to post.
389 $user2 = self::getDataGenerator()->create_user();
390 $user3 = self::getDataGenerator()->create_user();
391
392 // Set the first created user to the test user.
393 self::setUser($user1);
394
395 // Create course to add the module.
396 $course1 = self::getDataGenerator()->create_course();
397
398 // Forum with tracking off.
399 $record = new stdClass();
400 $record->course = $course1->id;
401 $record->trackingtype = FORUM_TRACKING_OFF;
402 $forum1 = self::getDataGenerator()->create_module('forum', $record);
403 $forum1context = context_module::instance($forum1->cmid);
404
405 // Add discussions to the forums.
406 $record = new stdClass();
407 $record->course = $course1->id;
408 $record->userid = $user1->id;
409 $record->forum = $forum1->id;
410 $discussion1 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
411
412 $record = new stdClass();
413 $record->course = $course1->id;
414 $record->userid = $user2->id;
415 $record->forum = $forum1->id;
416 $discussion2 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
417
418 // Add 2 replies to the discussion 1 from different users.
419 $record = new stdClass();
420 $record->discussion = $discussion1->id;
421 $record->parent = $discussion1->firstpost;
422 $record->userid = $user2->id;
423 $discussion1reply1 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_post($record);
424
425 $record->parent = $discussion1reply1->id;
426 $record->userid = $user3->id;
427 $discussion1reply2 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_post($record);
428
429 // Enrol the user in the course.
430 $enrol = enrol_get_plugin('manual');
431 // Following line enrol and assign default role id to the user.
432 // So the user automatically gets mod/forum:viewdiscussion on all forums of the course.
433 $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
434 $this->getDataGenerator()->enrol_user($user2->id, $course1->id);
81f810dc
JL
435
436 // Delete one user, to test that we still receive posts by this user.
437 delete_user($user3);
e2ede426
JL
438
439 // Create what we expect to be returned when querying the discussion.
440 $expectedposts = array(
441 'posts' => array(),
442 'warnings' => array(),
443 );
694bf0c7 444
81f810dc
JL
445 // Empty picture since it's a user deleted (user3).
446 $userpictureurl = '';
694bf0c7 447
e2ede426
JL
448 $expectedposts['posts'][] = array(
449 'id' => $discussion1reply2->id,
450 'discussion' => $discussion1reply2->discussion,
451 'parent' => $discussion1reply2->parent,
48fb0250 452 'userid' => (int) $discussion1reply2->userid,
e2ede426
JL
453 'created' => $discussion1reply2->created,
454 'modified' => $discussion1reply2->modified,
455 'mailed' => $discussion1reply2->mailed,
456 'subject' => $discussion1reply2->subject,
457 'message' => file_rewrite_pluginfile_urls($discussion1reply2->message, 'pluginfile.php',
458 $forum1context->id, 'mod_forum', 'post', $discussion1reply2->id),
48fb0250 459 'messageformat' => 1, // This value is usually changed by external_format_text() function.
e2ede426
JL
460 'messagetrust' => $discussion1reply2->messagetrust,
461 'attachment' => $discussion1reply2->attachment,
462 'totalscore' => $discussion1reply2->totalscore,
463 'mailnow' => $discussion1reply2->mailnow,
464 'children' => array(),
465 'canreply' => true,
466 'postread' => false,
694bf0c7
JL
467 'userfullname' => fullname($user3),
468 'userpictureurl' => $userpictureurl
e2ede426 469 );
694bf0c7 470
da1be050
JL
471 $userpictureurl = moodle_url::make_webservice_pluginfile_url(
472 context_user::instance($discussion1reply1->userid)->id, 'user', 'icon', null, '/', 'f1')->out(false);
694bf0c7 473
e2ede426
JL
474 $expectedposts['posts'][] = array(
475 'id' => $discussion1reply1->id,
476 'discussion' => $discussion1reply1->discussion,
477 'parent' => $discussion1reply1->parent,
48fb0250 478 'userid' => (int) $discussion1reply1->userid,
e2ede426
JL
479 'created' => $discussion1reply1->created,
480 'modified' => $discussion1reply1->modified,
481 'mailed' => $discussion1reply1->mailed,
482 'subject' => $discussion1reply1->subject,
483 'message' => file_rewrite_pluginfile_urls($discussion1reply1->message, 'pluginfile.php',
484 $forum1context->id, 'mod_forum', 'post', $discussion1reply1->id),
48fb0250 485 'messageformat' => 1, // This value is usually changed by external_format_text() function.
e2ede426
JL
486 'messagetrust' => $discussion1reply1->messagetrust,
487 'attachment' => $discussion1reply1->attachment,
488 'totalscore' => $discussion1reply1->totalscore,
489 'mailnow' => $discussion1reply1->mailnow,
d2c58b95 490 'children' => array($discussion1reply2->id),
e2ede426
JL
491 'canreply' => true,
492 'postread' => false,
694bf0c7
JL
493 'userfullname' => fullname($user2),
494 'userpictureurl' => $userpictureurl
e2ede426
JL
495 );
496
497 // Test a discussion with two additional posts (total 3 posts).
498 $posts = mod_forum_external::get_forum_discussion_posts($discussion1->id, 'modified', 'DESC');
499 $posts = external_api::clean_returnvalue(mod_forum_external::get_forum_discussion_posts_returns(), $posts);
500 $this->assertEquals(3, count($posts['posts']));
501
502 // Unset the initial discussion post.
503 array_pop($posts['posts']);
504 $this->assertEquals($expectedposts, $posts);
505
506 // Test discussion without additional posts. There should be only one post (the one created by the discussion).
507 $posts = mod_forum_external::get_forum_discussion_posts($discussion2->id, 'modified', 'DESC');
508 $posts = external_api::clean_returnvalue(mod_forum_external::get_forum_discussion_posts_returns(), $posts);
509 $this->assertEquals(1, count($posts['posts']));
510
511 }
c2586672
JL
512
513 /**
514 * Test get forum discussions paginated
515 */
516 public function test_mod_forum_get_forum_discussions_paginated() {
517 global $USER, $CFG, $DB;
518
519 $this->resetAfterTest(true);
520
521 // Set the CFG variable to allow track forums.
522 $CFG->forum_trackreadposts = true;
523
524 // Create a user who can track forums.
525 $record = new stdClass();
526 $record->trackforums = true;
527 $user1 = self::getDataGenerator()->create_user($record);
528 // Create a bunch of other users to post.
529 $user2 = self::getDataGenerator()->create_user();
530 $user3 = self::getDataGenerator()->create_user();
531 $user4 = self::getDataGenerator()->create_user();
532
533 // Set the first created user to the test user.
534 self::setUser($user1);
535
536 // Create courses to add the modules.
537 $course1 = self::getDataGenerator()->create_course();
538
539 // First forum with tracking off.
540 $record = new stdClass();
541 $record->course = $course1->id;
542 $record->trackingtype = FORUM_TRACKING_OFF;
543 $forum1 = self::getDataGenerator()->create_module('forum', $record);
544
545 // Add discussions to the forums.
546 $record = new stdClass();
547 $record->course = $course1->id;
548 $record->userid = $user1->id;
549 $record->forum = $forum1->id;
550 $discussion1 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
551
552 // Add three replies to the discussion 1 from different users.
553 $record = new stdClass();
554 $record->discussion = $discussion1->id;
555 $record->parent = $discussion1->firstpost;
556 $record->userid = $user2->id;
557 $discussion1reply1 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_post($record);
558
559 $record->parent = $discussion1reply1->id;
560 $record->userid = $user3->id;
561 $discussion1reply2 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_post($record);
562
563 $record->userid = $user4->id;
564 $discussion1reply3 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_post($record);
565
566 // Enrol the user in the first course.
567 $enrol = enrol_get_plugin('manual');
568
569 // We don't use the dataGenerator as we need to get the $instance2 to unenrol later.
570 $enrolinstances = enrol_get_instances($course1->id, true);
571 foreach ($enrolinstances as $courseenrolinstance) {
572 if ($courseenrolinstance->enrol == "manual") {
573 $instance1 = $courseenrolinstance;
574 break;
575 }
576 }
577 $enrol->enrol_user($instance1, $user1->id);
578
81f810dc
JL
579 // Delete one user.
580 delete_user($user4);
581
c2586672
JL
582 // Assign capabilities to view discussions for forum 1.
583 $cm = get_coursemodule_from_id('forum', $forum1->cmid, 0, false, MUST_EXIST);
584 $context = context_module::instance($cm->id);
585 $newrole = create_role('Role 2', 'role2', 'Role 2 description');
586 $this->assignUserCapability('mod/forum:viewdiscussion', $context->id, $newrole);
587
588 // Create what we expect to be returned when querying the forums.
589
590 $post1 = $DB->get_record('forum_posts', array('id' => $discussion1->firstpost), '*', MUST_EXIST);
81f810dc 591 $userpictureurl = moodle_url::make_webservice_pluginfile_url(
c2586672 592 context_user::instance($user1->id)->id, 'user', 'icon', null, '/', 'f1');
c2586672 593
81f810dc
JL
594 // We expect an empty URL since we deleted the user4.
595 $usermodifiedpictureurl = '';
c2586672
JL
596
597 $expecteddiscussions = array(
598 'id' => $discussion1->firstpost,
599 'name' => $discussion1->name,
600 'groupid' => $discussion1->groupid,
601 'timemodified' => $discussion1reply3->created,
602 'usermodified' => $discussion1reply3->userid,
603 'timestart' => $discussion1->timestart,
604 'timeend' => $discussion1->timeend,
605 'discussion' => $discussion1->id,
606 'parent' => 0,
607 'userid' => $discussion1->userid,
608 'created' => $post1->created,
609 'modified' => $post1->modified,
610 'mailed' => $post1->mailed,
611 'subject' => $post1->subject,
612 'message' => $post1->message,
613 'messageformat' => $post1->messageformat,
614 'messagetrust' => $post1->messagetrust,
615 'attachment' => $post1->attachment,
616 'totalscore' => $post1->totalscore,
617 'mailnow' => $post1->mailnow,
618 'userfullname' => fullname($user1),
619 'usermodifiedfullname' => fullname($user4),
620 'userpictureurl' => $userpictureurl,
621 'usermodifiedpictureurl' => $usermodifiedpictureurl,
622 'numreplies' => 3,
623 'numunread' => 0
624 );
625
626 // Call the external function passing forum id.
627 $discussions = mod_forum_external::get_forum_discussions_paginated($forum1->id);
628 $discussions = external_api::clean_returnvalue(mod_forum_external::get_forum_discussions_paginated_returns(), $discussions);
629 $expectedreturn = array(
630 'discussions' => array($expecteddiscussions),
631 'warnings' => array()
632 );
633 $this->assertEquals($expectedreturn, $discussions);
634
635 // Call without required view discussion capability.
636 $this->unassignUserCapability('mod/forum:viewdiscussion', $context->id, $newrole);
637 try {
638 mod_forum_external::get_forum_discussions_paginated($forum1->id);
639 $this->fail('Exception expected due to missing capability.');
640 } catch (moodle_exception $e) {
641 $this->assertEquals('noviewdiscussionspermission', $e->errorcode);
642 }
643
644 // Unenrol user from second course.
645 $enrol->unenrol_user($instance1, $user1->id);
646
647 // Call for the second course we unenrolled the user from, make sure exception thrown.
648 try {
649 mod_forum_external::get_forum_discussions_paginated($forum1->id);
650 $this->fail('Exception expected due to being unenrolled from the course.');
651 } catch (moodle_exception $e) {
652 $this->assertEquals('requireloginerror', $e->errorcode);
653 }
654 }
2b9fe87d 655}