Merge branch 'MDL-53166' of https://github.com/eugeneventer/moodle-fixes
[moodle.git] / mod / forum / tests / subscriptions_test.php
CommitLineData
59075a43
AN
1<?php
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16
17/**
18 * The module forums tests
19 *
20 * @package mod_forum
21 * @copyright 2013 Frédéric Massart
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
25defined('MOODLE_INTERNAL') || die();
26
27global $CFG;
28require_once($CFG->dirroot . '/mod/forum/lib.php');
29
30class mod_forum_subscriptions_testcase extends advanced_testcase {
31
32 /**
33 * Test setUp.
34 */
35 public function setUp() {
36 // We must clear the subscription caches. This has to be done both before each test, and after in case of other
37 // tests using these functions.
38 \mod_forum\subscriptions::reset_forum_cache();
e3bbfb52 39 \mod_forum\subscriptions::reset_discussion_cache();
59075a43
AN
40 }
41
42 /**
43 * Test tearDown.
44 */
45 public function tearDown() {
46 // We must clear the subscription caches. This has to be done both before each test, and after in case of other
47 // tests using these functions.
48 \mod_forum\subscriptions::reset_forum_cache();
e3bbfb52 49 \mod_forum\subscriptions::reset_discussion_cache();
59075a43
AN
50 }
51
52 /**
53 * Helper to create the required number of users in the specified
54 * course.
55 * Users are enrolled as students.
56 *
57 * @param stdClass $course The course object
58 * @param integer $count The number of users to create
59 * @return array The users created
60 */
61 protected function helper_create_users($course, $count) {
62 $users = array();
63
64 for ($i = 0; $i < $count; $i++) {
65 $user = $this->getDataGenerator()->create_user();
66 $this->getDataGenerator()->enrol_user($user->id, $course->id);
67 $users[] = $user;
68 }
69
70 return $users;
71 }
72
73 /**
74 * Create a new discussion and post within the specified forum, as the
75 * specified author.
76 *
77 * @param stdClass $forum The forum to post in
78 * @param stdClass $author The author to post as
79 * @param array An array containing the discussion object, and the post object
80 */
81 protected function helper_post_to_forum($forum, $author) {
eb451c79 82 global $DB;
59075a43
AN
83 $generator = $this->getDataGenerator()->get_plugin_generator('mod_forum');
84
85 // Create a discussion in the forum, and then add a post to that discussion.
86 $record = new stdClass();
87 $record->course = $forum->course;
88 $record->userid = $author->id;
89 $record->forum = $forum->id;
90 $discussion = $generator->create_discussion($record);
91
eb451c79
AN
92 // Retrieve the post which was created by create_discussion.
93 $post = $DB->get_record('forum_posts', array('discussion' => $discussion->id));
59075a43
AN
94
95 return array($discussion, $post);
96 }
97
98 public function test_subscription_modes() {
99 global $DB;
100
101 $this->resetAfterTest(true);
102
103 // Create a course, with a forum.
104 $course = $this->getDataGenerator()->create_course();
105
106 $options = array('course' => $course->id);
107 $forum = $this->getDataGenerator()->create_module('forum', $options);
108
109 \mod_forum\subscriptions::set_subscription_mode($forum->id, FORUM_FORCESUBSCRIBE);
110 $forum = $DB->get_record('forum', array('id' => $forum->id));
111 $this->assertEquals(FORUM_FORCESUBSCRIBE, \mod_forum\subscriptions::get_subscription_mode($forum));
112 $this->assertTrue(\mod_forum\subscriptions::is_forcesubscribed($forum));
113 $this->assertFalse(\mod_forum\subscriptions::is_subscribable($forum));
114 $this->assertFalse(\mod_forum\subscriptions::subscription_disabled($forum));
115
116 \mod_forum\subscriptions::set_subscription_mode($forum->id, FORUM_DISALLOWSUBSCRIBE);
117 $forum = $DB->get_record('forum', array('id' => $forum->id));
118 $this->assertEquals(FORUM_DISALLOWSUBSCRIBE, \mod_forum\subscriptions::get_subscription_mode($forum));
119 $this->assertTrue(\mod_forum\subscriptions::subscription_disabled($forum));
120 $this->assertFalse(\mod_forum\subscriptions::is_subscribable($forum));
121 $this->assertFalse(\mod_forum\subscriptions::is_forcesubscribed($forum));
122
123 \mod_forum\subscriptions::set_subscription_mode($forum->id, FORUM_INITIALSUBSCRIBE);
124 $forum = $DB->get_record('forum', array('id' => $forum->id));
125 $this->assertEquals(FORUM_INITIALSUBSCRIBE, \mod_forum\subscriptions::get_subscription_mode($forum));
126 $this->assertTrue(\mod_forum\subscriptions::is_subscribable($forum));
127 $this->assertFalse(\mod_forum\subscriptions::subscription_disabled($forum));
128 $this->assertFalse(\mod_forum\subscriptions::is_forcesubscribed($forum));
129
130 \mod_forum\subscriptions::set_subscription_mode($forum->id, FORUM_CHOOSESUBSCRIBE);
131 $forum = $DB->get_record('forum', array('id' => $forum->id));
132 $this->assertEquals(FORUM_CHOOSESUBSCRIBE, \mod_forum\subscriptions::get_subscription_mode($forum));
133 $this->assertTrue(\mod_forum\subscriptions::is_subscribable($forum));
134 $this->assertFalse(\mod_forum\subscriptions::subscription_disabled($forum));
135 $this->assertFalse(\mod_forum\subscriptions::is_forcesubscribed($forum));
136 }
137
138 /**
139 * Test fetching unsubscribable forums.
140 */
141 public function test_unsubscribable_forums() {
142 global $DB;
143
144 $this->resetAfterTest(true);
145
146 // Create a course, with a forum.
147 $course = $this->getDataGenerator()->create_course();
148
149 // Create a user enrolled in the course as a student.
150 list($user) = $this->helper_create_users($course, 1);
151
152 // Must be logged in as the current user.
153 $this->setUser($user);
154
155 // Without any subscriptions, there should be nothing returned.
156 $result = \mod_forum\subscriptions::get_unsubscribable_forums();
157 $this->assertEquals(0, count($result));
158
159 // Create the forums.
160 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_FORCESUBSCRIBE);
161 $forceforum = $this->getDataGenerator()->create_module('forum', $options);
162 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_DISALLOWSUBSCRIBE);
163 $disallowforum = $this->getDataGenerator()->create_module('forum', $options);
164 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_CHOOSESUBSCRIBE);
165 $chooseforum = $this->getDataGenerator()->create_module('forum', $options);
166 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_INITIALSUBSCRIBE);
167 $initialforum = $this->getDataGenerator()->create_module('forum', $options);
168
169 // At present the user is only subscribed to the initial forum.
170 $result = \mod_forum\subscriptions::get_unsubscribable_forums();
171 $this->assertEquals(1, count($result));
172
173 // Ensure that the user is enrolled in all of the forums except force subscribed.
174 \mod_forum\subscriptions::subscribe_user($user->id, $disallowforum);
175 \mod_forum\subscriptions::subscribe_user($user->id, $chooseforum);
176
177 $result = \mod_forum\subscriptions::get_unsubscribable_forums();
178 $this->assertEquals(3, count($result));
179
180 // Hide the forums.
181 set_coursemodule_visible($forceforum->cmid, 0);
182 set_coursemodule_visible($disallowforum->cmid, 0);
183 set_coursemodule_visible($chooseforum->cmid, 0);
184 set_coursemodule_visible($initialforum->cmid, 0);
185 $result = \mod_forum\subscriptions::get_unsubscribable_forums();
186 $this->assertEquals(0, count($result));
187
188 // Add the moodle/course:viewhiddenactivities capability to the student user.
189 $roleids = $DB->get_records_menu('role', null, '', 'shortname, id');
190 $context = \context_course::instance($course->id);
191 assign_capability('moodle/course:viewhiddenactivities', CAP_ALLOW, $roleids['student'], $context);
192 $context->mark_dirty();
193
194 // All of the unsubscribable forums should now be listed.
195 $result = \mod_forum\subscriptions::get_unsubscribable_forums();
196 $this->assertEquals(3, count($result));
197 }
198
e3bbfb52
AN
199 /**
200 * Test that toggling the forum-level subscription for a different user does not affect their discussion-level
201 * subscriptions.
202 */
203 public function test_forum_subscribe_toggle_as_other() {
204 global $DB;
205
206 $this->resetAfterTest(true);
207
208 // Create a course, with a forum.
209 $course = $this->getDataGenerator()->create_course();
210
211 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_CHOOSESUBSCRIBE);
212 $forum = $this->getDataGenerator()->create_module('forum', $options);
213
214 // Create a user enrolled in the course as a student.
215 list($author) = $this->helper_create_users($course, 1);
216
217 // Post a discussion to the forum.
218 list($discussion, $post) = $this->helper_post_to_forum($forum, $author);
219
220 // Check that the user is currently not subscribed to the forum.
221 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
222
223 // Check the deprecated function too.
224 $this->assertFalse(forum_is_subscribed($author->id, $forum));
5ecf8e8f
T
225 $this->assertEquals(1, count($this->getDebuggingMessages()));
226 $this->resetDebugging();
e3bbfb52
AN
227
228 // Check that the user is unsubscribed from the discussion too.
229 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum, $discussion->id));
230
231 // Check that we have no records in either of the subscription tables.
232 $this->assertEquals(0, $DB->count_records('forum_subscriptions', array(
233 'userid' => $author->id,
234 'forum' => $forum->id,
235 )));
236 $this->assertEquals(0, $DB->count_records('forum_discussion_subs', array(
237 'userid' => $author->id,
238 'discussion' => $discussion->id,
239 )));
240
241 // Subscribing to the forum should create a record in the subscriptions table, but not the forum discussion
242 // subscriptions table.
243 \mod_forum\subscriptions::subscribe_user($author->id, $forum);
244 $this->assertEquals(1, $DB->count_records('forum_subscriptions', array(
245 'userid' => $author->id,
246 'forum' => $forum->id,
247 )));
248 $this->assertEquals(0, $DB->count_records('forum_discussion_subs', array(
249 'userid' => $author->id,
250 'discussion' => $discussion->id,
251 )));
252
253 // Unsubscribing should remove the record from the forum subscriptions table, and not modify the forum
254 // discussion subscriptions table.
255 \mod_forum\subscriptions::unsubscribe_user($author->id, $forum);
256 $this->assertEquals(0, $DB->count_records('forum_subscriptions', array(
257 'userid' => $author->id,
258 'forum' => $forum->id,
259 )));
260 $this->assertEquals(0, $DB->count_records('forum_discussion_subs', array(
261 'userid' => $author->id,
262 'discussion' => $discussion->id,
263 )));
264
265 // The same thing should happen calling the deprecated versions of
266 // these functions.
267 // Subscribing to the forum should create a record in the subscriptions table, but not the forum discussion
268 // subscriptions table.
269 forum_subscribe($author->id, $forum->id);
5ecf8e8f
T
270 $this->assertEquals(1, count($this->getDebuggingMessages()));
271 $this->resetDebugging();
e3bbfb52
AN
272 $this->assertEquals(1, $DB->count_records('forum_subscriptions', array(
273 'userid' => $author->id,
274 'forum' => $forum->id,
275 )));
276 $this->assertEquals(0, $DB->count_records('forum_discussion_subs', array(
277 'userid' => $author->id,
278 'discussion' => $discussion->id,
279 )));
280
281 // Unsubscribing should remove the record from the forum subscriptions table, and not modify the forum
282 // discussion subscriptions table.
283 forum_unsubscribe($author->id, $forum->id);
5ecf8e8f
T
284 $this->assertEquals(1, count($this->getDebuggingMessages()));
285 $this->resetDebugging();
e3bbfb52
AN
286 $this->assertEquals(0, $DB->count_records('forum_subscriptions', array(
287 'userid' => $author->id,
288 'forum' => $forum->id,
289 )));
290 $this->assertEquals(0, $DB->count_records('forum_discussion_subs', array(
291 'userid' => $author->id,
292 'discussion' => $discussion->id,
293 )));
294
295 // Enroling the user in the discussion should add one record to the forum discussion table without modifying the
296 // form subscriptions.
297 \mod_forum\subscriptions::subscribe_user_to_discussion($author->id, $discussion);
298 $this->assertEquals(0, $DB->count_records('forum_subscriptions', array(
299 'userid' => $author->id,
300 'forum' => $forum->id,
301 )));
302 $this->assertEquals(1, $DB->count_records('forum_discussion_subs', array(
303 'userid' => $author->id,
304 'discussion' => $discussion->id,
305 )));
306
307 // Unsubscribing should remove the record from the forum subscriptions table, and not modify the forum
308 // discussion subscriptions table.
309 \mod_forum\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion);
310 $this->assertEquals(0, $DB->count_records('forum_subscriptions', array(
311 'userid' => $author->id,
312 'forum' => $forum->id,
313 )));
314 $this->assertEquals(0, $DB->count_records('forum_discussion_subs', array(
315 'userid' => $author->id,
316 'discussion' => $discussion->id,
317 )));
318
319 // Re-subscribe to the discussion so that we can check the effect of forum-level subscriptions.
320 \mod_forum\subscriptions::subscribe_user_to_discussion($author->id, $discussion);
321 $this->assertEquals(0, $DB->count_records('forum_subscriptions', array(
322 'userid' => $author->id,
323 'forum' => $forum->id,
324 )));
325 $this->assertEquals(1, $DB->count_records('forum_discussion_subs', array(
326 'userid' => $author->id,
327 'discussion' => $discussion->id,
328 )));
329
330 // Subscribing to the forum should have no effect on the forum discussion subscriptions table if the user did
331 // not request the change themself.
332 \mod_forum\subscriptions::subscribe_user($author->id, $forum);
333 $this->assertEquals(1, $DB->count_records('forum_subscriptions', array(
334 'userid' => $author->id,
335 'forum' => $forum->id,
336 )));
337 $this->assertEquals(1, $DB->count_records('forum_discussion_subs', array(
338 'userid' => $author->id,
339 'discussion' => $discussion->id,
340 )));
341
342 // Unsubscribing from the forum should have no effect on the forum discussion subscriptions table if the user
343 // did not request the change themself.
344 \mod_forum\subscriptions::unsubscribe_user($author->id, $forum);
345 $this->assertEquals(0, $DB->count_records('forum_subscriptions', array(
346 'userid' => $author->id,
347 'forum' => $forum->id,
348 )));
349 $this->assertEquals(1, $DB->count_records('forum_discussion_subs', array(
350 'userid' => $author->id,
351 'discussion' => $discussion->id,
352 )));
353
354 // Subscribing to the forum should remove the per-discussion subscription preference if the user requested the
355 // change themself.
356 \mod_forum\subscriptions::subscribe_user($author->id, $forum, null, true);
357 $this->assertEquals(1, $DB->count_records('forum_subscriptions', array(
358 'userid' => $author->id,
359 'forum' => $forum->id,
360 )));
361 $this->assertEquals(0, $DB->count_records('forum_discussion_subs', array(
362 'userid' => $author->id,
363 'discussion' => $discussion->id,
364 )));
365
366 // Now unsubscribe from the current discussion whilst being subscribed to the forum as a whole.
367 \mod_forum\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion);
368 $this->assertEquals(1, $DB->count_records('forum_subscriptions', array(
369 'userid' => $author->id,
370 'forum' => $forum->id,
371 )));
372 $this->assertEquals(1, $DB->count_records('forum_discussion_subs', array(
373 'userid' => $author->id,
374 'discussion' => $discussion->id,
375 )));
376
377 // Unsubscribing from the forum should remove the per-discussion subscription preference if the user requested the
378 // change themself.
379 \mod_forum\subscriptions::unsubscribe_user($author->id, $forum, null, true);
380 $this->assertEquals(0, $DB->count_records('forum_subscriptions', array(
381 'userid' => $author->id,
382 'forum' => $forum->id,
383 )));
384 $this->assertEquals(0, $DB->count_records('forum_discussion_subs', array(
385 'userid' => $author->id,
386 'discussion' => $discussion->id,
387 )));
388
389 // Subscribe to the discussion.
390 \mod_forum\subscriptions::subscribe_user_to_discussion($author->id, $discussion);
391 $this->assertEquals(0, $DB->count_records('forum_subscriptions', array(
392 'userid' => $author->id,
393 'forum' => $forum->id,
394 )));
395 $this->assertEquals(1, $DB->count_records('forum_discussion_subs', array(
396 'userid' => $author->id,
397 'discussion' => $discussion->id,
398 )));
399
400 // Subscribe to the forum without removing the discussion preferences.
401 \mod_forum\subscriptions::subscribe_user($author->id, $forum);
402 $this->assertEquals(1, $DB->count_records('forum_subscriptions', array(
403 'userid' => $author->id,
404 'forum' => $forum->id,
405 )));
406 $this->assertEquals(1, $DB->count_records('forum_discussion_subs', array(
407 'userid' => $author->id,
408 'discussion' => $discussion->id,
409 )));
410
411 // Unsubscribing from the discussion should result in a change.
412 \mod_forum\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion);
413 $this->assertEquals(1, $DB->count_records('forum_subscriptions', array(
414 'userid' => $author->id,
415 'forum' => $forum->id,
416 )));
417 $this->assertEquals(1, $DB->count_records('forum_discussion_subs', array(
418 'userid' => $author->id,
419 'discussion' => $discussion->id,
420 )));
421
422 }
423
424 /**
425 * Test that a user unsubscribed from a forum is not subscribed to it's discussions by default.
426 */
427 public function test_forum_discussion_subscription_forum_unsubscribed() {
428 $this->resetAfterTest(true);
429
430 // Create a course, with a forum.
431 $course = $this->getDataGenerator()->create_course();
432
433 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_CHOOSESUBSCRIBE);
434 $forum = $this->getDataGenerator()->create_module('forum', $options);
435
436 // Create users enrolled in the course as students.
437 list($author) = $this->helper_create_users($course, 1);
438
439 // Check that the user is currently not subscribed to the forum.
440 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
441
442 // Check the deprecated function too.
443 $this->assertFalse(forum_is_subscribed($author->id, $forum));
5ecf8e8f
T
444 $this->assertEquals(1, count($this->getDebuggingMessages()));
445 $this->resetDebugging();
e3bbfb52
AN
446
447 // Post a discussion to the forum.
448 list($discussion, $post) = $this->helper_post_to_forum($forum, $author);
449
450 // Check that the user is unsubscribed from the discussion too.
451 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum, $discussion->id));
452 }
453
454 /**
455 * Test that the act of subscribing to a forum subscribes the user to it's discussions by default.
456 */
457 public function test_forum_discussion_subscription_forum_subscribed() {
458 $this->resetAfterTest(true);
459
460 // Create a course, with a forum.
461 $course = $this->getDataGenerator()->create_course();
462
463 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_CHOOSESUBSCRIBE);
464 $forum = $this->getDataGenerator()->create_module('forum', $options);
465
466 // Create users enrolled in the course as students.
467 list($author) = $this->helper_create_users($course, 1);
468
469 // Enrol the user in the forum.
470 // If a subscription was added, we get the record ID.
471 $this->assertInternalType('int', \mod_forum\subscriptions::subscribe_user($author->id, $forum));
472
473 // If we already have a subscription when subscribing the user, we get a boolean (true).
474 $this->assertTrue(\mod_forum\subscriptions::subscribe_user($author->id, $forum));
475
476 // Check that the user is currently subscribed to the forum.
477 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
478
479 // Check the deprecated function too.
480 $this->assertTrue(forum_is_subscribed($author->id, $forum));
5ecf8e8f
T
481 $this->assertEquals(1, count($this->getDebuggingMessages()));
482 $this->resetDebugging();
e3bbfb52
AN
483
484 // Post a discussion to the forum.
485 list($discussion, $post) = $this->helper_post_to_forum($forum, $author);
486
487 // Check that the user is subscribed to the discussion too.
488 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($author->id, $forum, $discussion->id));
489 }
490
491 /**
492 * Test that a user unsubscribed from a forum can be subscribed to a discussion.
493 */
494 public function test_forum_discussion_subscription_forum_unsubscribed_discussion_subscribed() {
495 $this->resetAfterTest(true);
496
497 // Create a course, with a forum.
498 $course = $this->getDataGenerator()->create_course();
499
500 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_CHOOSESUBSCRIBE);
501 $forum = $this->getDataGenerator()->create_module('forum', $options);
502
503 // Create a user enrolled in the course as a student.
504 list($author) = $this->helper_create_users($course, 1);
505
506 // Check that the user is currently not subscribed to the forum.
507 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
508
509 // Check the deprecated function too.
510 $this->assertFalse(forum_is_subscribed($author->id, $forum));
5ecf8e8f
T
511 $this->assertEquals(1, count($this->getDebuggingMessages()));
512 $this->resetDebugging();
e3bbfb52
AN
513
514 // Post a discussion to the forum.
515 list($discussion, $post) = $this->helper_post_to_forum($forum, $author);
516
517 // Attempting to unsubscribe from the discussion should not make a change.
518 $this->assertFalse(\mod_forum\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion));
519
520 // Then subscribe them to the discussion.
521 $this->assertTrue(\mod_forum\subscriptions::subscribe_user_to_discussion($author->id, $discussion));
522
523 // Check that the user is still unsubscribed from the forum.
524 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
525
526 // Check the deprecated function too.
527 $this->assertFalse(forum_is_subscribed($author->id, $forum));
5ecf8e8f
T
528 $this->assertEquals(1, count($this->getDebuggingMessages()));
529 $this->resetDebugging();
e3bbfb52
AN
530
531 // But subscribed to the discussion.
532 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($author->id, $forum, $discussion->id));
533 }
534
535 /**
536 * Test that a user subscribed to a forum can be unsubscribed from a discussion.
537 */
538 public function test_forum_discussion_subscription_forum_subscribed_discussion_unsubscribed() {
539 $this->resetAfterTest(true);
540
541 // Create a course, with a forum.
542 $course = $this->getDataGenerator()->create_course();
543
544 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_CHOOSESUBSCRIBE);
545 $forum = $this->getDataGenerator()->create_module('forum', $options);
546
547 // Create two users enrolled in the course as students.
548 list($author) = $this->helper_create_users($course, 2);
549
550 // Enrol the student in the forum.
551 \mod_forum\subscriptions::subscribe_user($author->id, $forum);
552
553 // Check that the user is currently subscribed to the forum.
554 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
555
556 // Check the deprecated function too.
557 $this->assertTrue(forum_is_subscribed($author->id, $forum));
5ecf8e8f
T
558 $this->assertEquals(1, count($this->getDebuggingMessages()));
559 $this->resetDebugging();
e3bbfb52
AN
560
561 // Post a discussion to the forum.
562 list($discussion, $post) = $this->helper_post_to_forum($forum, $author);
563
564 // Then unsubscribe them from the discussion.
565 \mod_forum\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion);
566
567 // Check that the user is still subscribed to the forum.
568 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
569
570 // Check the deprecated function too.
571 $this->assertTrue(forum_is_subscribed($author->id, $forum));
5ecf8e8f
T
572 $this->assertEquals(1, count($this->getDebuggingMessages()));
573 $this->resetDebugging();
e3bbfb52
AN
574
575 // But unsubscribed from the discussion.
576 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum, $discussion->id));
577 }
578
579 /**
580 * Test the effect of toggling the discussion subscription status when subscribed to the forum.
581 */
582 public function test_forum_discussion_toggle_forum_subscribed() {
583 global $DB;
584
585 $this->resetAfterTest(true);
586
587 // Create a course, with a forum.
588 $course = $this->getDataGenerator()->create_course();
589
590 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_CHOOSESUBSCRIBE);
591 $forum = $this->getDataGenerator()->create_module('forum', $options);
592
593 // Create two users enrolled in the course as students.
594 list($author) = $this->helper_create_users($course, 2);
595
596 // Enrol the student in the forum.
597 \mod_forum\subscriptions::subscribe_user($author->id, $forum);
598
599 // Check that the user is currently subscribed to the forum.
600 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
601
602 // Check the deprecated function too.
603 $this->assertTrue(forum_is_subscribed($author->id, $forum));
5ecf8e8f
T
604 $this->assertEquals(1, count($this->getDebuggingMessages()));
605 $this->resetDebugging();
e3bbfb52
AN
606
607 // Post a discussion to the forum.
608 list($discussion, $post) = $this->helper_post_to_forum($forum, $author);
609
610 // Check that the user is initially subscribed to that discussion.
611 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($author->id, $forum, $discussion->id));
612
613 // An attempt to subscribe again should result in a falsey return to indicate that no change was made.
614 $this->assertFalse(\mod_forum\subscriptions::subscribe_user_to_discussion($author->id, $discussion));
615
616 // And there should be no discussion subscriptions (and one forum subscription).
617 $this->assertEquals(0, $DB->count_records('forum_discussion_subs', array(
618 'userid' => $author->id,
619 'discussion' => $discussion->id,
620 )));
621 $this->assertEquals(1, $DB->count_records('forum_subscriptions', array(
622 'userid' => $author->id,
623 'forum' => $forum->id,
624 )));
625
626 // Then unsubscribe them from the discussion.
627 \mod_forum\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion);
628
629 // Check that the user is still subscribed to the forum.
630 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
631
632 // Check the deprecated function too.
633 $this->assertTrue(forum_is_subscribed($author->id, $forum));
5ecf8e8f
T
634 $this->assertEquals(1, count($this->getDebuggingMessages()));
635 $this->resetDebugging();
e3bbfb52
AN
636
637 // An attempt to unsubscribe again should result in a falsey return to indicate that no change was made.
638 $this->assertFalse(\mod_forum\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion));
639
640 // And there should be a discussion subscriptions (and one forum subscription).
641 $this->assertEquals(1, $DB->count_records('forum_discussion_subs', array(
642 'userid' => $author->id,
643 'discussion' => $discussion->id,
644 )));
645 $this->assertEquals(1, $DB->count_records('forum_subscriptions', array(
646 'userid' => $author->id,
647 'forum' => $forum->id,
648 )));
649
650 // But unsubscribed from the discussion.
651 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum, $discussion->id));
652
653 // There should be a record in the discussion subscription tracking table.
654 $this->assertEquals(1, $DB->count_records('forum_discussion_subs', array(
655 'userid' => $author->id,
656 'discussion' => $discussion->id,
657 )));
658
659 // And one in the forum subscription tracking table.
660 $this->assertEquals(1, $DB->count_records('forum_subscriptions', array(
661 'userid' => $author->id,
662 'forum' => $forum->id,
663 )));
664
665 // Now subscribe the user again to the discussion.
666 \mod_forum\subscriptions::subscribe_user_to_discussion($author->id, $discussion);
667
668 // Check that the user is still subscribed to the forum.
669 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
670
671 // Check the deprecated function too.
672 $this->assertTrue(forum_is_subscribed($author->id, $forum));
5ecf8e8f
T
673 $this->assertEquals(1, count($this->getDebuggingMessages()));
674 $this->resetDebugging();
e3bbfb52
AN
675
676 // Check the deprecated function too.
677 $this->assertTrue(forum_is_subscribed($author->id, $forum));
5ecf8e8f
T
678 $this->assertEquals(1, count($this->getDebuggingMessages()));
679 $this->resetDebugging();
e3bbfb52
AN
680
681 // And is subscribed to the discussion again.
682 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($author->id, $forum, $discussion->id));
683
684 // There should be no record in the discussion subscription tracking table.
685 $this->assertEquals(0, $DB->count_records('forum_discussion_subs', array(
686 'userid' => $author->id,
687 'discussion' => $discussion->id,
688 )));
689
690 // And one in the forum subscription tracking table.
691 $this->assertEquals(1, $DB->count_records('forum_subscriptions', array(
692 'userid' => $author->id,
693 'forum' => $forum->id,
694 )));
695
696 // And unsubscribe again.
697 \mod_forum\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion);
698
699 // Check that the user is still subscribed to the forum.
700 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
701
702 // Check the deprecated function too.
703 $this->assertTrue(forum_is_subscribed($author->id, $forum));
5ecf8e8f
T
704 $this->assertEquals(1, count($this->getDebuggingMessages()));
705 $this->resetDebugging();
e3bbfb52
AN
706
707 // But unsubscribed from the discussion.
708 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum, $discussion->id));
709
710 // There should be a record in the discussion subscription tracking table.
711 $this->assertEquals(1, $DB->count_records('forum_discussion_subs', array(
712 'userid' => $author->id,
713 'discussion' => $discussion->id,
714 )));
715
716 // And one in the forum subscription tracking table.
717 $this->assertEquals(1, $DB->count_records('forum_subscriptions', array(
718 'userid' => $author->id,
719 'forum' => $forum->id,
720 )));
721
722 // And subscribe the user again to the discussion.
723 \mod_forum\subscriptions::subscribe_user_to_discussion($author->id, $discussion);
724
725 // Check that the user is still subscribed to the forum.
726 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
727 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
728
729 // And is subscribed to the discussion again.
730 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($author->id, $forum, $discussion->id));
731
732 // There should be no record in the discussion subscription tracking table.
733 $this->assertEquals(0, $DB->count_records('forum_discussion_subs', array(
734 'userid' => $author->id,
735 'discussion' => $discussion->id,
736 )));
737
738 // And one in the forum subscription tracking table.
739 $this->assertEquals(1, $DB->count_records('forum_subscriptions', array(
740 'userid' => $author->id,
741 'forum' => $forum->id,
742 )));
743
744 // And unsubscribe again.
745 \mod_forum\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion);
746
747 // Check that the user is still subscribed to the forum.
748 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
749
750 // Check the deprecated function too.
751 $this->assertTrue(forum_is_subscribed($author->id, $forum));
5ecf8e8f
T
752 $this->assertEquals(1, count($this->getDebuggingMessages()));
753 $this->resetDebugging();
e3bbfb52
AN
754
755 // But unsubscribed from the discussion.
756 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum, $discussion->id));
757
758 // There should be a record in the discussion subscription tracking table.
759 $this->assertEquals(1, $DB->count_records('forum_discussion_subs', array(
760 'userid' => $author->id,
761 'discussion' => $discussion->id,
762 )));
763
764 // And one in the forum subscription tracking table.
765 $this->assertEquals(1, $DB->count_records('forum_subscriptions', array(
766 'userid' => $author->id,
767 'forum' => $forum->id,
768 )));
769
770 // Now unsubscribe the user from the forum.
771 $this->assertTrue(\mod_forum\subscriptions::unsubscribe_user($author->id, $forum, null, true));
772
773 // This removes both the forum_subscriptions, and the forum_discussion_subs records.
774 $this->assertEquals(0, $DB->count_records('forum_discussion_subs', array(
775 'userid' => $author->id,
776 'discussion' => $discussion->id,
777 )));
778 $this->assertEquals(0, $DB->count_records('forum_subscriptions', array(
779 'userid' => $author->id,
780 'forum' => $forum->id,
781 )));
782
783 // And should have reset the discussion cache value.
784 $result = \mod_forum\subscriptions::fetch_discussion_subscription($forum->id, $author->id);
785 $this->assertInternalType('array', $result);
786 $this->assertFalse(isset($result[$discussion->id]));
787 }
788
789 /**
790 * Test the effect of toggling the discussion subscription status when unsubscribed from the forum.
791 */
792 public function test_forum_discussion_toggle_forum_unsubscribed() {
793 global $DB;
794
795 $this->resetAfterTest(true);
796
797 // Create a course, with a forum.
798 $course = $this->getDataGenerator()->create_course();
799
800 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_CHOOSESUBSCRIBE);
801 $forum = $this->getDataGenerator()->create_module('forum', $options);
802
803 // Create two users enrolled in the course as students.
804 list($author) = $this->helper_create_users($course, 2);
805
806 // Check that the user is currently unsubscribed to the forum.
807 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
808
809 // Check the deprecated function too.
810 $this->assertFalse(forum_is_subscribed($author->id, $forum));
5ecf8e8f
T
811 $this->assertEquals(1, count($this->getDebuggingMessages()));
812 $this->resetDebugging();
e3bbfb52
AN
813
814 // Post a discussion to the forum.
815 list($discussion, $post) = $this->helper_post_to_forum($forum, $author);
816
817 // Check that the user is initially unsubscribed to that discussion.
818 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum, $discussion->id));
819
820 // Then subscribe them to the discussion.
821 $this->assertTrue(\mod_forum\subscriptions::subscribe_user_to_discussion($author->id, $discussion));
822
823 // An attempt to subscribe again should result in a falsey return to indicate that no change was made.
824 $this->assertFalse(\mod_forum\subscriptions::subscribe_user_to_discussion($author->id, $discussion));
825
826 // Check that the user is still unsubscribed from the forum.
827 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
828
829 // Check the deprecated function too.
830 $this->assertFalse(forum_is_subscribed($author->id, $forum));
5ecf8e8f
T
831 $this->assertEquals(1, count($this->getDebuggingMessages()));
832 $this->resetDebugging();
e3bbfb52
AN
833
834 // But subscribed to the discussion.
835 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($author->id, $forum, $discussion->id));
836
837 // There should be a record in the discussion subscription tracking table.
838 $this->assertEquals(1, $DB->count_records('forum_discussion_subs', array(
839 'userid' => $author->id,
840 'discussion' => $discussion->id,
841 )));
842
843 // Now unsubscribe the user again from the discussion.
844 \mod_forum\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion);
845
846 // Check that the user is still unsubscribed from the forum.
847 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
848
849 // Check the deprecated function too.
850 $this->assertFalse(forum_is_subscribed($author->id, $forum));
5ecf8e8f
T
851 $this->assertEquals(1, count($this->getDebuggingMessages()));
852 $this->resetDebugging();
e3bbfb52
AN
853
854 // And is unsubscribed from the discussion again.
855 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum, $discussion->id));
856
857 // There should be no record in the discussion subscription tracking table.
858 $this->assertEquals(0, $DB->count_records('forum_discussion_subs', array(
859 'userid' => $author->id,
860 'discussion' => $discussion->id,
861 )));
862
863 // And subscribe the user again to the discussion.
864 \mod_forum\subscriptions::subscribe_user_to_discussion($author->id, $discussion);
865
866 // Check that the user is still unsubscribed from the forum.
867 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
868
869 // Check the deprecated function too.
870 $this->assertFalse(forum_is_subscribed($author->id, $forum));
5ecf8e8f
T
871 $this->assertEquals(1, count($this->getDebuggingMessages()));
872 $this->resetDebugging();
e3bbfb52
AN
873
874 // And is subscribed to the discussion again.
875 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($author->id, $forum, $discussion->id));
876
877 // There should be a record in the discussion subscription tracking table.
878 $this->assertEquals(1, $DB->count_records('forum_discussion_subs', array(
879 'userid' => $author->id,
880 'discussion' => $discussion->id,
881 )));
882
883 // And unsubscribe again.
884 \mod_forum\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion);
885
886 // Check that the user is still unsubscribed from the forum.
887 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
888
889 // Check the deprecated function too.
890 $this->assertFalse(forum_is_subscribed($author->id, $forum));
5ecf8e8f
T
891 $this->assertEquals(1, count($this->getDebuggingMessages()));
892 $this->resetDebugging();
e3bbfb52
AN
893
894 // But unsubscribed from the discussion.
895 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum, $discussion->id));
896
897 // There should be no record in the discussion subscription tracking table.
898 $this->assertEquals(0, $DB->count_records('forum_discussion_subs', array(
899 'userid' => $author->id,
900 'discussion' => $discussion->id,
901 )));
902 }
903
59075a43
AN
904 /**
905 * Test that the deprecated forum_is_subscribed accepts numeric forum IDs.
906 */
907 public function test_forum_is_subscribed_numeric() {
908 global $DB;
909
910 $this->resetAfterTest(true);
911
912 // Create a course, with a forum.
913 $course = $this->getDataGenerator()->create_course();
914
915 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_CHOOSESUBSCRIBE);
916 $forum = $this->getDataGenerator()->create_module('forum', $options);
917
918 // Create a user enrolled in the course as a students.
919 list($author) = $this->helper_create_users($course, 1);
920
921 // Check that the user is currently unsubscribed to the forum.
922 $this->assertFalse(forum_is_subscribed($author->id, $forum->id));
5ecf8e8f
T
923 $this->assertEquals(1, count($this->getDebuggingMessages()));
924 $this->resetDebugging();
59075a43
AN
925
926 // It should match the result of when it's called with the forum object.
927 $this->assertFalse(forum_is_subscribed($author->id, $forum));
5ecf8e8f
T
928 $this->assertEquals(1, count($this->getDebuggingMessages()));
929 $this->resetDebugging();
59075a43
AN
930
931 // And when the user is subscribed, we should also get the correct result.
932 \mod_forum\subscriptions::subscribe_user($author->id, $forum);
933
934 $this->assertTrue(forum_is_subscribed($author->id, $forum->id));
5ecf8e8f
T
935 $this->assertEquals(1, count($this->getDebuggingMessages()));
936 $this->resetDebugging();
59075a43
AN
937
938 // It should match the result of when it's called with the forum object.
939 $this->assertTrue(forum_is_subscribed($author->id, $forum));
5ecf8e8f
T
940 $this->assertEquals(1, count($this->getDebuggingMessages()));
941 $this->resetDebugging();
59075a43
AN
942 }
943
944 /**
945 * Test that the correct users are returned when fetching subscribed users from a forum where users can choose to
946 * subscribe and unsubscribe.
947 */
948 public function test_fetch_subscribed_users_subscriptions() {
949 global $DB, $CFG;
950
951 $this->resetAfterTest(true);
952
953 // Create a course, with a forum. where users are initially subscribed.
954 $course = $this->getDataGenerator()->create_course();
955 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_INITIALSUBSCRIBE);
956 $forum = $this->getDataGenerator()->create_module('forum', $options);
957
958 // Create some user enrolled in the course as a student.
959 $usercount = 5;
960 $users = $this->helper_create_users($course, $usercount);
961
962 // All users should be subscribed.
963 $subscribers = \mod_forum\subscriptions::fetch_subscribed_users($forum);
964 $this->assertEquals($usercount, count($subscribers));
965
966 // Subscribe the guest user too to the forum - they should never be returned by this function.
967 $this->getDataGenerator()->enrol_user($CFG->siteguest, $course->id);
968 $subscribers = \mod_forum\subscriptions::fetch_subscribed_users($forum);
969 $this->assertEquals($usercount, count($subscribers));
970
971 // Unsubscribe 2 users.
972 $unsubscribedcount = 2;
973 for ($i = 0; $i < $unsubscribedcount; $i++) {
974 \mod_forum\subscriptions::unsubscribe_user($users[$i]->id, $forum);
975 }
976
977 // The subscription count should now take into account those users who have been unsubscribed.
978 $subscribers = \mod_forum\subscriptions::fetch_subscribed_users($forum);
979 $this->assertEquals($usercount - $unsubscribedcount, count($subscribers));
980 }
981
982 /**
983 * Test that the correct users are returned hwen fetching subscribed users from a forum where users are forcibly
984 * subscribed.
985 */
986 public function test_fetch_subscribed_users_forced() {
987 global $DB;
988
989 $this->resetAfterTest(true);
990
991 // Create a course, with a forum. where users are initially subscribed.
992 $course = $this->getDataGenerator()->create_course();
993 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_FORCESUBSCRIBE);
994 $forum = $this->getDataGenerator()->create_module('forum', $options);
995
996 // Create some user enrolled in the course as a student.
997 $usercount = 5;
998 $users = $this->helper_create_users($course, $usercount);
999
1000 // All users should be subscribed.
1001 $subscribers = \mod_forum\subscriptions::fetch_subscribed_users($forum);
1002 $this->assertEquals($usercount, count($subscribers));
1003 }
1004
e3bbfb52
AN
1005 /**
1006 * Test that unusual combinations of discussion subscriptions do not affect the subscribed user list.
1007 */
1008 public function test_fetch_subscribed_users_discussion_subscriptions() {
1009 global $DB;
1010
1011 $this->resetAfterTest(true);
1012
1013 // Create a course, with a forum. where users are initially subscribed.
1014 $course = $this->getDataGenerator()->create_course();
1015 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_INITIALSUBSCRIBE);
1016 $forum = $this->getDataGenerator()->create_module('forum', $options);
1017
1018 // Create some user enrolled in the course as a student.
1019 $usercount = 5;
1020 $users = $this->helper_create_users($course, $usercount);
1021
1022 list($discussion, $post) = $this->helper_post_to_forum($forum, $users[0]);
1023
1024 // All users should be subscribed.
1025 $subscribers = \mod_forum\subscriptions::fetch_subscribed_users($forum);
1026 $this->assertEquals($usercount, count($subscribers));
1027 $subscribers = \mod_forum\subscriptions::fetch_subscribed_users($forum, 0, null, null, true);
1028 $this->assertEquals($usercount, count($subscribers));
1029
1030 \mod_forum\subscriptions::unsubscribe_user_from_discussion($users[0]->id, $discussion);
1031
1032 // All users should be subscribed.
1033 $subscribers = \mod_forum\subscriptions::fetch_subscribed_users($forum);
1034 $this->assertEquals($usercount, count($subscribers));
1035
1036 // All users should be subscribed.
1037 $subscribers = \mod_forum\subscriptions::fetch_subscribed_users($forum, 0, null, null, true);
1038 $this->assertEquals($usercount, count($subscribers));
1039
1040 // Manually insert an extra subscription for one of the users.
1041 $record = new stdClass();
1042 $record->userid = $users[2]->id;
1043 $record->forum = $forum->id;
1044 $record->discussion = $discussion->id;
eb451c79 1045 $record->preference = time();
e3bbfb52
AN
1046 $DB->insert_record('forum_discussion_subs', $record);
1047
1048 // The discussion count should not have changed.
1049 $subscribers = \mod_forum\subscriptions::fetch_subscribed_users($forum);
1050 $this->assertEquals($usercount, count($subscribers));
1051 $subscribers = \mod_forum\subscriptions::fetch_subscribed_users($forum, 0, null, null, true);
1052 $this->assertEquals($usercount, count($subscribers));
1053
1054 // Unsubscribe 2 users.
1055 $unsubscribedcount = 2;
1056 for ($i = 0; $i < $unsubscribedcount; $i++) {
1057 \mod_forum\subscriptions::unsubscribe_user($users[$i]->id, $forum);
1058 }
1059
1060 // The subscription count should now take into account those users who have been unsubscribed.
1061 $subscribers = \mod_forum\subscriptions::fetch_subscribed_users($forum);
1062 $this->assertEquals($usercount - $unsubscribedcount, count($subscribers));
1063 $subscribers = \mod_forum\subscriptions::fetch_subscribed_users($forum, 0, null, null, true);
1064 $this->assertEquals($usercount - $unsubscribedcount, count($subscribers));
1065
1066 // Now subscribe one of those users back to the discussion.
1067 $subscribeddiscussionusers = 1;
1068 for ($i = 0; $i < $subscribeddiscussionusers; $i++) {
1069 \mod_forum\subscriptions::subscribe_user_to_discussion($users[$i]->id, $discussion);
1070 }
1071 $subscribers = \mod_forum\subscriptions::fetch_subscribed_users($forum);
1072 $this->assertEquals($usercount - $unsubscribedcount, count($subscribers));
1073 $subscribers = \mod_forum\subscriptions::fetch_subscribed_users($forum, 0, null, null, true);
1074 $this->assertEquals($usercount - $unsubscribedcount + $subscribeddiscussionusers, count($subscribers));
1075 }
1076
59075a43
AN
1077 /**
1078 * Test whether a user is force-subscribed to a forum.
1079 */
1080 public function test_force_subscribed_to_forum() {
1081 global $DB;
1082
1083 $this->resetAfterTest(true);
1084
1085 // Create a course, with a forum.
1086 $course = $this->getDataGenerator()->create_course();
1087
1088 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_FORCESUBSCRIBE);
1089 $forum = $this->getDataGenerator()->create_module('forum', $options);
1090
1091 // Create a user enrolled in the course as a student.
1092 $roleids = $DB->get_records_menu('role', null, '', 'shortname, id');
1093 $user = $this->getDataGenerator()->create_user();
1094 $this->getDataGenerator()->enrol_user($user->id, $course->id, $roleids['student']);
1095
1096 // Check that the user is currently subscribed to the forum.
1097 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($user->id, $forum));
1098
1099 // Remove the allowforcesubscribe capability from the user.
1100 $cm = get_coursemodule_from_instance('forum', $forum->id);
1101 $context = \context_module::instance($cm->id);
1102 assign_capability('mod/forum:allowforcesubscribe', CAP_PROHIBIT, $roleids['student'], $context);
1103 $context->mark_dirty();
1104 $this->assertFalse(has_capability('mod/forum:allowforcesubscribe', $context, $user->id));
1105
1106 // Check that the user is no longer subscribed to the forum.
1107 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($user->id, $forum));
1108 }
1109
e3bbfb52
AN
1110 /**
1111 * Test that the subscription cache can be pre-filled.
1112 */
1113 public function test_subscription_cache_prefill() {
1114 global $DB;
1115
1116 $this->resetAfterTest(true);
1117
1118 // Create a course, with a forum.
1119 $course = $this->getDataGenerator()->create_course();
1120
1121 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_INITIALSUBSCRIBE);
1122 $forum = $this->getDataGenerator()->create_module('forum', $options);
1123
1124 // Create some users.
1125 $users = $this->helper_create_users($course, 20);
1126
1127 // Reset the subscription cache.
1128 \mod_forum\subscriptions::reset_forum_cache();
1129
1130 // Filling the subscription cache should only use a single query.
1131 $startcount = $DB->perf_get_reads();
1132 $this->assertNull(\mod_forum\subscriptions::fill_subscription_cache($forum->id));
1133 $postfillcount = $DB->perf_get_reads();
1134 $this->assertEquals(1, $postfillcount - $startcount);
1135
1136 // Now fetch some subscriptions from that forum - these should use
1137 // the cache and not perform additional queries.
1138 foreach ($users as $user) {
1139 $this->assertTrue(\mod_forum\subscriptions::fetch_subscription_cache($forum->id, $user->id));
1140 }
1141 $finalcount = $DB->perf_get_reads();
1142 $this->assertEquals(0, $finalcount - $postfillcount);
1143 }
1144
1145 /**
1146 * Test that the subscription cache can filled user-at-a-time.
1147 */
1148 public function test_subscription_cache_fill() {
1149 global $DB;
1150
1151 $this->resetAfterTest(true);
1152
1153 // Create a course, with a forum.
1154 $course = $this->getDataGenerator()->create_course();
1155
1156 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_INITIALSUBSCRIBE);
1157 $forum = $this->getDataGenerator()->create_module('forum', $options);
1158
1159 // Create some users.
1160 $users = $this->helper_create_users($course, 20);
1161
1162 // Reset the subscription cache.
1163 \mod_forum\subscriptions::reset_forum_cache();
1164
1165 // Filling the subscription cache should only use a single query.
1166 $startcount = $DB->perf_get_reads();
1167
1168 // Fetch some subscriptions from that forum - these should not use the cache and will perform additional queries.
1169 foreach ($users as $user) {
1170 $this->assertTrue(\mod_forum\subscriptions::fetch_subscription_cache($forum->id, $user->id));
1171 }
1172 $finalcount = $DB->perf_get_reads();
1173 $this->assertEquals(20, $finalcount - $startcount);
1174 }
1175
1176 /**
1177 * Test that the discussion subscription cache can filled course-at-a-time.
1178 */
1179 public function test_discussion_subscription_cache_fill_for_course() {
1180 global $DB;
1181
1182 $this->resetAfterTest(true);
1183
1184 // Create a course, with a forum.
1185 $course = $this->getDataGenerator()->create_course();
1186
1187 // Create the forums.
1188 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_DISALLOWSUBSCRIBE);
1189 $disallowforum = $this->getDataGenerator()->create_module('forum', $options);
1190 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_CHOOSESUBSCRIBE);
1191 $chooseforum = $this->getDataGenerator()->create_module('forum', $options);
1192 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_INITIALSUBSCRIBE);
1193 $initialforum = $this->getDataGenerator()->create_module('forum', $options);
1194
1195 // Create some users and keep a reference to the first user.
1196 $users = $this->helper_create_users($course, 20);
1197 $user = reset($users);
1198
1199 // Reset the subscription caches.
1200 \mod_forum\subscriptions::reset_forum_cache();
1201
1202 $startcount = $DB->perf_get_reads();
1203 $result = \mod_forum\subscriptions::fill_subscription_cache_for_course($course->id, $user->id);
1204 $this->assertNull($result);
1205 $postfillcount = $DB->perf_get_reads();
1206 $this->assertEquals(1, $postfillcount - $startcount);
1207 $this->assertFalse(\mod_forum\subscriptions::fetch_subscription_cache($disallowforum->id, $user->id));
1208 $this->assertFalse(\mod_forum\subscriptions::fetch_subscription_cache($chooseforum->id, $user->id));
1209 $this->assertTrue(\mod_forum\subscriptions::fetch_subscription_cache($initialforum->id, $user->id));
1210 $finalcount = $DB->perf_get_reads();
1211 $this->assertEquals(0, $finalcount - $postfillcount);
1212
1213 // Test for all users.
1214 foreach ($users as $user) {
1215 $result = \mod_forum\subscriptions::fill_subscription_cache_for_course($course->id, $user->id);
1216 $this->assertFalse(\mod_forum\subscriptions::fetch_subscription_cache($disallowforum->id, $user->id));
1217 $this->assertFalse(\mod_forum\subscriptions::fetch_subscription_cache($chooseforum->id, $user->id));
1218 $this->assertTrue(\mod_forum\subscriptions::fetch_subscription_cache($initialforum->id, $user->id));
1219 }
1220 $finalcount = $DB->perf_get_reads();
1221 $this->assertEquals(count($users), $finalcount - $postfillcount);
1222 }
1223
1224 /**
1225 * Test that the discussion subscription cache can be forcibly updated for a user.
1226 */
1227 public function test_discussion_subscription_cache_prefill() {
1228 global $DB;
1229
1230 $this->resetAfterTest(true);
1231
1232 // Create a course, with a forum.
1233 $course = $this->getDataGenerator()->create_course();
1234
1235 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_INITIALSUBSCRIBE);
1236 $forum = $this->getDataGenerator()->create_module('forum', $options);
1237
1238 // Create some users.
1239 $users = $this->helper_create_users($course, 20);
1240
1241 // Post some discussions to the forum.
1242 $discussions = array();
1243 $author = $users[0];
1244 for ($i = 0; $i < 20; $i++) {
1245 list($discussion, $post) = $this->helper_post_to_forum($forum, $author);
1246 $discussions[] = $discussion;
1247 }
1248
1249 // Unsubscribe half the users from the half the discussions.
1250 $forumcount = 0;
1251 $usercount = 0;
1252 foreach ($discussions as $data) {
1253 if ($forumcount % 2) {
1254 continue;
1255 }
1256 foreach ($users as $user) {
1257 if ($usercount % 2) {
1258 continue;
1259 }
1260 \mod_forum\subscriptions::unsubscribe_user_from_discussion($user->id, $discussion);
1261 $usercount++;
1262 }
1263 $forumcount++;
1264 }
1265
1266 // Reset the subscription caches.
1267 \mod_forum\subscriptions::reset_forum_cache();
1268 \mod_forum\subscriptions::reset_discussion_cache();
1269
1270 // Filling the discussion subscription cache should only use a single query.
1271 $startcount = $DB->perf_get_reads();
1272 $this->assertNull(\mod_forum\subscriptions::fill_discussion_subscription_cache($forum->id));
1273 $postfillcount = $DB->perf_get_reads();
1274 $this->assertEquals(1, $postfillcount - $startcount);
1275
1276 // Now fetch some subscriptions from that forum - these should use
1277 // the cache and not perform additional queries.
1278 foreach ($users as $user) {
1279 $result = \mod_forum\subscriptions::fetch_discussion_subscription($forum->id, $user->id);
1280 $this->assertInternalType('array', $result);
1281 }
1282 $finalcount = $DB->perf_get_reads();
1283 $this->assertEquals(0, $finalcount - $postfillcount);
1284 }
1285
1286 /**
1287 * Test that the discussion subscription cache can filled user-at-a-time.
1288 */
1289 public function test_discussion_subscription_cache_fill() {
1290 global $DB;
1291
1292 $this->resetAfterTest(true);
1293
1294 // Create a course, with a forum.
1295 $course = $this->getDataGenerator()->create_course();
1296
1297 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_INITIALSUBSCRIBE);
1298 $forum = $this->getDataGenerator()->create_module('forum', $options);
1299
1300 // Create some users.
1301 $users = $this->helper_create_users($course, 20);
1302
1303 // Post some discussions to the forum.
1304 $discussions = array();
1305 $author = $users[0];
1306 for ($i = 0; $i < 20; $i++) {
1307 list($discussion, $post) = $this->helper_post_to_forum($forum, $author);
1308 $discussions[] = $discussion;
1309 }
1310
1311 // Unsubscribe half the users from the half the discussions.
1312 $forumcount = 0;
1313 $usercount = 0;
1314 foreach ($discussions as $data) {
1315 if ($forumcount % 2) {
1316 continue;
1317 }
1318 foreach ($users as $user) {
1319 if ($usercount % 2) {
1320 continue;
1321 }
1322 \mod_forum\subscriptions::unsubscribe_user_from_discussion($user->id, $discussion);
1323 $usercount++;
1324 }
1325 $forumcount++;
1326 }
1327
1328 // Reset the subscription caches.
1329 \mod_forum\subscriptions::reset_forum_cache();
1330 \mod_forum\subscriptions::reset_discussion_cache();
1331
1332 $startcount = $DB->perf_get_reads();
1333
1334 // Now fetch some subscriptions from that forum - these should use
1335 // the cache and not perform additional queries.
1336 foreach ($users as $user) {
1337 $result = \mod_forum\subscriptions::fetch_discussion_subscription($forum->id, $user->id);
1338 $this->assertInternalType('array', $result);
1339 }
1340 $finalcount = $DB->perf_get_reads();
1341 $this->assertEquals(20, $finalcount - $startcount);
1342 }
1343
1344 /**
1345 * Test that after toggling the forum subscription as another user,
1346 * the discussion subscription functionality works as expected.
1347 */
1348 public function test_forum_subscribe_toggle_as_other_repeat_subscriptions() {
1349 global $DB;
1350
1351 $this->resetAfterTest(true);
1352
1353 // Create a course, with a forum.
1354 $course = $this->getDataGenerator()->create_course();
1355
1356 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_CHOOSESUBSCRIBE);
1357 $forum = $this->getDataGenerator()->create_module('forum', $options);
1358
1359 // Create a user enrolled in the course as a student.
1360 list($user) = $this->helper_create_users($course, 1);
1361
1362 // Post a discussion to the forum.
1363 list($discussion, $post) = $this->helper_post_to_forum($forum, $user);
1364
1365 // Confirm that the user is currently not subscribed to the forum.
1366 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($user->id, $forum));
1367
1368 // Confirm that the user is unsubscribed from the discussion too.
1369 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($user->id, $forum, $discussion->id));
1370
1371 // Confirm that we have no records in either of the subscription tables.
1372 $this->assertEquals(0, $DB->count_records('forum_subscriptions', array(
1373 'userid' => $user->id,
1374 'forum' => $forum->id,
1375 )));
1376 $this->assertEquals(0, $DB->count_records('forum_discussion_subs', array(
1377 'userid' => $user->id,
1378 'discussion' => $discussion->id,
1379 )));
1380
1381 // Subscribing to the forum should create a record in the subscriptions table, but not the forum discussion
1382 // subscriptions table.
1383 \mod_forum\subscriptions::subscribe_user($user->id, $forum);
1384 $this->assertEquals(1, $DB->count_records('forum_subscriptions', array(
1385 'userid' => $user->id,
1386 'forum' => $forum->id,
1387 )));
1388 $this->assertEquals(0, $DB->count_records('forum_discussion_subs', array(
1389 'userid' => $user->id,
1390 'discussion' => $discussion->id,
1391 )));
1392
1393 // Now unsubscribe from the discussion. This should return true.
1394 $this->assertTrue(\mod_forum\subscriptions::unsubscribe_user_from_discussion($user->id, $discussion));
1395
1396 // Attempting to unsubscribe again should return false because no change was made.
1397 $this->assertFalse(\mod_forum\subscriptions::unsubscribe_user_from_discussion($user->id, $discussion));
1398
1399 // Subscribing to the discussion again should return truthfully as the subscription preference was removed.
1400 $this->assertTrue(\mod_forum\subscriptions::subscribe_user_to_discussion($user->id, $discussion));
1401
1402 // Attempting to subscribe again should return false because no change was made.
1403 $this->assertFalse(\mod_forum\subscriptions::subscribe_user_to_discussion($user->id, $discussion));
1404
1405 // Now unsubscribe from the discussion. This should return true once more.
1406 $this->assertTrue(\mod_forum\subscriptions::unsubscribe_user_from_discussion($user->id, $discussion));
1407
1408 // And unsubscribing from the forum but not as a request from the user should maintain their preference.
1409 \mod_forum\subscriptions::unsubscribe_user($user->id, $forum);
1410
1411 $this->assertEquals(0, $DB->count_records('forum_subscriptions', array(
1412 'userid' => $user->id,
1413 'forum' => $forum->id,
1414 )));
1415 $this->assertEquals(1, $DB->count_records('forum_discussion_subs', array(
1416 'userid' => $user->id,
1417 'discussion' => $discussion->id,
1418 )));
1419
1420 // Subscribing to the discussion should return truthfully because a change was made.
1421 $this->assertTrue(\mod_forum\subscriptions::subscribe_user_to_discussion($user->id, $discussion));
1422 $this->assertEquals(0, $DB->count_records('forum_subscriptions', array(
1423 'userid' => $user->id,
1424 'forum' => $forum->id,
1425 )));
1426 $this->assertEquals(1, $DB->count_records('forum_discussion_subs', array(
1427 'userid' => $user->id,
1428 'discussion' => $discussion->id,
1429 )));
1430 }
1431
4238983e
AN
1432 /**
1433 * Test that providing a context_module instance to is_subscribed does not result in additional lookups to retrieve
1434 * the context_module.
1435 */
1436 public function test_is_subscribed_cm() {
1437 global $DB;
1438
1439 $this->resetAfterTest(true);
1440
1441 // Create a course, with a forum.
1442 $course = $this->getDataGenerator()->create_course();
1443
1444 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_FORCESUBSCRIBE);
1445 $forum = $this->getDataGenerator()->create_module('forum', $options);
1446
1447 // Create a user enrolled in the course as a student.
1448 list($user) = $this->helper_create_users($course, 1);
1449
1450 // Retrieve the $cm now.
1451 $cm = get_fast_modinfo($forum->course)->instances['forum'][$forum->id];
1452
1453 // Reset get_fast_modinfo.
1454 get_fast_modinfo(0, 0, true);
1455
1456 // Call is_subscribed without passing the $cmid - this should result in a lookup and filling of some of the
1457 // caches. This provides us with consistent data to start from.
1458 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($user->id, $forum));
1459 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($user->id, $forum));
1460
1461 // Make a note of the number of DB calls.
1462 $basecount = $DB->perf_get_reads();
1463
1464 // Call is_subscribed - it should give return the correct result (False), and result in no additional queries.
1465 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($user->id, $forum, null, $cm));
1466
1467 // The capability check does require some queries, so we don't test it directly.
1468 // We don't assert here because this is dependant upon linked code which could change at any time.
1469 $suppliedcmcount = $DB->perf_get_reads() - $basecount;
1470
1471 // Call is_subscribed without passing the $cmid now - this should result in a lookup.
1472 get_fast_modinfo(0, 0, true);
1473 $basecount = $DB->perf_get_reads();
1474 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($user->id, $forum));
1475 $calculatedcmcount = $DB->perf_get_reads() - $basecount;
1476
1477 // There should be more queries than when we performed the same check a moment ago.
1478 $this->assertGreaterThan($suppliedcmcount, $calculatedcmcount);
1479 }
1480
59075a43 1481}