2 // This file is part of Moodle - http://moodle.org/
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.
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.
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/>.
18 * The module forums tests
21 * @copyright 2013 Frédéric Massart
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 defined('MOODLE_INTERNAL') || die();
28 require_once($CFG->dirroot . '/mod/forum/lib.php');
30 class mod_forum_subscriptions_testcase extends advanced_testcase {
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();
39 \mod_forum\subscriptions::reset_discussion_cache();
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();
49 \mod_forum\subscriptions::reset_discussion_cache();
53 * Helper to create the required number of users in the specified
55 * Users are enrolled as students.
57 * @param stdClass $course The course object
58 * @param integer $count The number of users to create
59 * @return array The users created
61 protected function helper_create_users($course, $count) {
64 for ($i = 0; $i < $count; $i++) {
65 $user = $this->getDataGenerator()->create_user();
66 $this->getDataGenerator()->enrol_user($user->id, $course->id);
74 * Create a new discussion and post within the specified forum, as the
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
81 protected function helper_post_to_forum($forum, $author) {
83 $generator = $this->getDataGenerator()->get_plugin_generator('mod_forum');
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);
92 // Retrieve the post which was created by create_discussion.
93 $post = $DB->get_record('forum_posts', array('discussion' => $discussion->id));
95 return array($discussion, $post);
98 public function test_subscription_modes() {
101 $this->resetAfterTest(true);
103 // Create a course, with a forum.
104 $course = $this->getDataGenerator()->create_course();
106 $options = array('course' => $course->id);
107 $forum = $this->getDataGenerator()->create_module('forum', $options);
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));
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));
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));
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));
139 * Test fetching unsubscribable forums.
141 public function test_unsubscribable_forums() {
144 $this->resetAfterTest(true);
146 // Create a course, with a forum.
147 $course = $this->getDataGenerator()->create_course();
149 // Create a user enrolled in the course as a student.
150 list($user) = $this->helper_create_users($course, 1);
152 // Must be logged in as the current user.
153 $this->setUser($user);
155 // Without any subscriptions, there should be nothing returned.
156 $result = \mod_forum\subscriptions::get_unsubscribable_forums();
157 $this->assertEquals(0, count($result));
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);
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));
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);
177 $result = \mod_forum\subscriptions::get_unsubscribable_forums();
178 $this->assertEquals(3, count($result));
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));
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();
194 // All of the unsubscribable forums should now be listed.
195 $result = \mod_forum\subscriptions::get_unsubscribable_forums();
196 $this->assertEquals(3, count($result));
200 * Test that toggling the forum-level subscription for a different user does not affect their discussion-level
203 public function test_forum_subscribe_toggle_as_other() {
206 $this->resetAfterTest(true);
208 // Create a course, with a forum.
209 $course = $this->getDataGenerator()->create_course();
211 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_CHOOSESUBSCRIBE);
212 $forum = $this->getDataGenerator()->create_module('forum', $options);
214 // Create a user enrolled in the course as a student.
215 list($author) = $this->helper_create_users($course, 1);
217 // Post a discussion to the forum.
218 list($discussion, $post) = $this->helper_post_to_forum($forum, $author);
220 // Check that the user is currently not subscribed to the forum.
221 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
223 // Check the deprecated function too.
224 $this->assertFalse(forum_is_subscribed($author->id, $forum));
225 $this->assertEquals(1, count($this->getDebuggingMessages()));
226 $this->resetDebugging();
228 // Check that the user is unsubscribed from the discussion too.
229 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum, $discussion->id));
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,
236 $this->assertEquals(0, $DB->count_records('forum_discussion_subs', array(
237 'userid' => $author->id,
238 'discussion' => $discussion->id,
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,
248 $this->assertEquals(0, $DB->count_records('forum_discussion_subs', array(
249 'userid' => $author->id,
250 'discussion' => $discussion->id,
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,
260 $this->assertEquals(0, $DB->count_records('forum_discussion_subs', array(
261 'userid' => $author->id,
262 'discussion' => $discussion->id,
265 // The same thing should happen calling the deprecated versions of
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);
270 $this->assertEquals(1, count($this->getDebuggingMessages()));
271 $this->resetDebugging();
272 $this->assertEquals(1, $DB->count_records('forum_subscriptions', array(
273 'userid' => $author->id,
274 'forum' => $forum->id,
276 $this->assertEquals(0, $DB->count_records('forum_discussion_subs', array(
277 'userid' => $author->id,
278 'discussion' => $discussion->id,
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);
284 $this->assertEquals(1, count($this->getDebuggingMessages()));
285 $this->resetDebugging();
286 $this->assertEquals(0, $DB->count_records('forum_subscriptions', array(
287 'userid' => $author->id,
288 'forum' => $forum->id,
290 $this->assertEquals(0, $DB->count_records('forum_discussion_subs', array(
291 'userid' => $author->id,
292 'discussion' => $discussion->id,
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,
302 $this->assertEquals(1, $DB->count_records('forum_discussion_subs', array(
303 'userid' => $author->id,
304 'discussion' => $discussion->id,
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,
314 $this->assertEquals(0, $DB->count_records('forum_discussion_subs', array(
315 'userid' => $author->id,
316 'discussion' => $discussion->id,
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,
325 $this->assertEquals(1, $DB->count_records('forum_discussion_subs', array(
326 'userid' => $author->id,
327 'discussion' => $discussion->id,
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,
337 $this->assertEquals(1, $DB->count_records('forum_discussion_subs', array(
338 'userid' => $author->id,
339 'discussion' => $discussion->id,
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,
349 $this->assertEquals(1, $DB->count_records('forum_discussion_subs', array(
350 'userid' => $author->id,
351 'discussion' => $discussion->id,
354 // Subscribing to the forum should remove the per-discussion subscription preference if the user requested the
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,
361 $this->assertEquals(0, $DB->count_records('forum_discussion_subs', array(
362 'userid' => $author->id,
363 'discussion' => $discussion->id,
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,
372 $this->assertEquals(1, $DB->count_records('forum_discussion_subs', array(
373 'userid' => $author->id,
374 'discussion' => $discussion->id,
377 // Unsubscribing from the forum should remove the per-discussion subscription preference if the user requested the
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,
384 $this->assertEquals(0, $DB->count_records('forum_discussion_subs', array(
385 'userid' => $author->id,
386 'discussion' => $discussion->id,
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,
395 $this->assertEquals(1, $DB->count_records('forum_discussion_subs', array(
396 'userid' => $author->id,
397 'discussion' => $discussion->id,
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,
406 $this->assertEquals(1, $DB->count_records('forum_discussion_subs', array(
407 'userid' => $author->id,
408 'discussion' => $discussion->id,
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,
417 $this->assertEquals(1, $DB->count_records('forum_discussion_subs', array(
418 'userid' => $author->id,
419 'discussion' => $discussion->id,
425 * Test that a user unsubscribed from a forum is not subscribed to it's discussions by default.
427 public function test_forum_discussion_subscription_forum_unsubscribed() {
428 $this->resetAfterTest(true);
430 // Create a course, with a forum.
431 $course = $this->getDataGenerator()->create_course();
433 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_CHOOSESUBSCRIBE);
434 $forum = $this->getDataGenerator()->create_module('forum', $options);
436 // Create users enrolled in the course as students.
437 list($author) = $this->helper_create_users($course, 1);
439 // Check that the user is currently not subscribed to the forum.
440 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
442 // Check the deprecated function too.
443 $this->assertFalse(forum_is_subscribed($author->id, $forum));
444 $this->assertEquals(1, count($this->getDebuggingMessages()));
445 $this->resetDebugging();
447 // Post a discussion to the forum.
448 list($discussion, $post) = $this->helper_post_to_forum($forum, $author);
450 // Check that the user is unsubscribed from the discussion too.
451 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum, $discussion->id));
455 * Test that the act of subscribing to a forum subscribes the user to it's discussions by default.
457 public function test_forum_discussion_subscription_forum_subscribed() {
458 $this->resetAfterTest(true);
460 // Create a course, with a forum.
461 $course = $this->getDataGenerator()->create_course();
463 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_CHOOSESUBSCRIBE);
464 $forum = $this->getDataGenerator()->create_module('forum', $options);
466 // Create users enrolled in the course as students.
467 list($author) = $this->helper_create_users($course, 1);
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));
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));
476 // Check that the user is currently subscribed to the forum.
477 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
479 // Check the deprecated function too.
480 $this->assertTrue(forum_is_subscribed($author->id, $forum));
481 $this->assertEquals(1, count($this->getDebuggingMessages()));
482 $this->resetDebugging();
484 // Post a discussion to the forum.
485 list($discussion, $post) = $this->helper_post_to_forum($forum, $author);
487 // Check that the user is subscribed to the discussion too.
488 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($author->id, $forum, $discussion->id));
492 * Test that a user unsubscribed from a forum can be subscribed to a discussion.
494 public function test_forum_discussion_subscription_forum_unsubscribed_discussion_subscribed() {
495 $this->resetAfterTest(true);
497 // Create a course, with a forum.
498 $course = $this->getDataGenerator()->create_course();
500 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_CHOOSESUBSCRIBE);
501 $forum = $this->getDataGenerator()->create_module('forum', $options);
503 // Create a user enrolled in the course as a student.
504 list($author) = $this->helper_create_users($course, 1);
506 // Check that the user is currently not subscribed to the forum.
507 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
509 // Check the deprecated function too.
510 $this->assertFalse(forum_is_subscribed($author->id, $forum));
511 $this->assertEquals(1, count($this->getDebuggingMessages()));
512 $this->resetDebugging();
514 // Post a discussion to the forum.
515 list($discussion, $post) = $this->helper_post_to_forum($forum, $author);
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));
520 // Then subscribe them to the discussion.
521 $this->assertTrue(\mod_forum\subscriptions::subscribe_user_to_discussion($author->id, $discussion));
523 // Check that the user is still unsubscribed from the forum.
524 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
526 // Check the deprecated function too.
527 $this->assertFalse(forum_is_subscribed($author->id, $forum));
528 $this->assertEquals(1, count($this->getDebuggingMessages()));
529 $this->resetDebugging();
531 // But subscribed to the discussion.
532 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($author->id, $forum, $discussion->id));
536 * Test that a user subscribed to a forum can be unsubscribed from a discussion.
538 public function test_forum_discussion_subscription_forum_subscribed_discussion_unsubscribed() {
539 $this->resetAfterTest(true);
541 // Create a course, with a forum.
542 $course = $this->getDataGenerator()->create_course();
544 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_CHOOSESUBSCRIBE);
545 $forum = $this->getDataGenerator()->create_module('forum', $options);
547 // Create two users enrolled in the course as students.
548 list($author) = $this->helper_create_users($course, 2);
550 // Enrol the student in the forum.
551 \mod_forum\subscriptions::subscribe_user($author->id, $forum);
553 // Check that the user is currently subscribed to the forum.
554 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
556 // Check the deprecated function too.
557 $this->assertTrue(forum_is_subscribed($author->id, $forum));
558 $this->assertEquals(1, count($this->getDebuggingMessages()));
559 $this->resetDebugging();
561 // Post a discussion to the forum.
562 list($discussion, $post) = $this->helper_post_to_forum($forum, $author);
564 // Then unsubscribe them from the discussion.
565 \mod_forum\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion);
567 // Check that the user is still subscribed to the forum.
568 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
570 // Check the deprecated function too.
571 $this->assertTrue(forum_is_subscribed($author->id, $forum));
572 $this->assertEquals(1, count($this->getDebuggingMessages()));
573 $this->resetDebugging();
575 // But unsubscribed from the discussion.
576 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum, $discussion->id));
580 * Test the effect of toggling the discussion subscription status when subscribed to the forum.
582 public function test_forum_discussion_toggle_forum_subscribed() {
585 $this->resetAfterTest(true);
587 // Create a course, with a forum.
588 $course = $this->getDataGenerator()->create_course();
590 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_CHOOSESUBSCRIBE);
591 $forum = $this->getDataGenerator()->create_module('forum', $options);
593 // Create two users enrolled in the course as students.
594 list($author) = $this->helper_create_users($course, 2);
596 // Enrol the student in the forum.
597 \mod_forum\subscriptions::subscribe_user($author->id, $forum);
599 // Check that the user is currently subscribed to the forum.
600 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
602 // Check the deprecated function too.
603 $this->assertTrue(forum_is_subscribed($author->id, $forum));
604 $this->assertEquals(1, count($this->getDebuggingMessages()));
605 $this->resetDebugging();
607 // Post a discussion to the forum.
608 list($discussion, $post) = $this->helper_post_to_forum($forum, $author);
610 // Check that the user is initially subscribed to that discussion.
611 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($author->id, $forum, $discussion->id));
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));
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,
621 $this->assertEquals(1, $DB->count_records('forum_subscriptions', array(
622 'userid' => $author->id,
623 'forum' => $forum->id,
626 // Then unsubscribe them from the discussion.
627 \mod_forum\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion);
629 // Check that the user is still subscribed to the forum.
630 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
632 // Check the deprecated function too.
633 $this->assertTrue(forum_is_subscribed($author->id, $forum));
634 $this->assertEquals(1, count($this->getDebuggingMessages()));
635 $this->resetDebugging();
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));
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,
645 $this->assertEquals(1, $DB->count_records('forum_subscriptions', array(
646 'userid' => $author->id,
647 'forum' => $forum->id,
650 // But unsubscribed from the discussion.
651 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum, $discussion->id));
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,
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,
665 // Now subscribe the user again to the discussion.
666 \mod_forum\subscriptions::subscribe_user_to_discussion($author->id, $discussion);
668 // Check that the user is still subscribed to the forum.
669 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
671 // Check the deprecated function too.
672 $this->assertTrue(forum_is_subscribed($author->id, $forum));
673 $this->assertEquals(1, count($this->getDebuggingMessages()));
674 $this->resetDebugging();
676 // Check the deprecated function too.
677 $this->assertTrue(forum_is_subscribed($author->id, $forum));
678 $this->assertEquals(1, count($this->getDebuggingMessages()));
679 $this->resetDebugging();
681 // And is subscribed to the discussion again.
682 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($author->id, $forum, $discussion->id));
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,
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,
696 // And unsubscribe again.
697 \mod_forum\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion);
699 // Check that the user is still subscribed to the forum.
700 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
702 // Check the deprecated function too.
703 $this->assertTrue(forum_is_subscribed($author->id, $forum));
704 $this->assertEquals(1, count($this->getDebuggingMessages()));
705 $this->resetDebugging();
707 // But unsubscribed from the discussion.
708 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum, $discussion->id));
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,
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,
722 // And subscribe the user again to the discussion.
723 \mod_forum\subscriptions::subscribe_user_to_discussion($author->id, $discussion);
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));
729 // And is subscribed to the discussion again.
730 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($author->id, $forum, $discussion->id));
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,
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,
744 // And unsubscribe again.
745 \mod_forum\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion);
747 // Check that the user is still subscribed to the forum.
748 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
750 // Check the deprecated function too.
751 $this->assertTrue(forum_is_subscribed($author->id, $forum));
752 $this->assertEquals(1, count($this->getDebuggingMessages()));
753 $this->resetDebugging();
755 // But unsubscribed from the discussion.
756 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum, $discussion->id));
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,
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,
770 // Now unsubscribe the user from the forum.
771 $this->assertTrue(\mod_forum\subscriptions::unsubscribe_user($author->id, $forum, null, true));
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,
778 $this->assertEquals(0, $DB->count_records('forum_subscriptions', array(
779 'userid' => $author->id,
780 'forum' => $forum->id,
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]));
790 * Test the effect of toggling the discussion subscription status when unsubscribed from the forum.
792 public function test_forum_discussion_toggle_forum_unsubscribed() {
795 $this->resetAfterTest(true);
797 // Create a course, with a forum.
798 $course = $this->getDataGenerator()->create_course();
800 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_CHOOSESUBSCRIBE);
801 $forum = $this->getDataGenerator()->create_module('forum', $options);
803 // Create two users enrolled in the course as students.
804 list($author) = $this->helper_create_users($course, 2);
806 // Check that the user is currently unsubscribed to the forum.
807 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
809 // Check the deprecated function too.
810 $this->assertFalse(forum_is_subscribed($author->id, $forum));
811 $this->assertEquals(1, count($this->getDebuggingMessages()));
812 $this->resetDebugging();
814 // Post a discussion to the forum.
815 list($discussion, $post) = $this->helper_post_to_forum($forum, $author);
817 // Check that the user is initially unsubscribed to that discussion.
818 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum, $discussion->id));
820 // Then subscribe them to the discussion.
821 $this->assertTrue(\mod_forum\subscriptions::subscribe_user_to_discussion($author->id, $discussion));
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));
826 // Check that the user is still unsubscribed from the forum.
827 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
829 // Check the deprecated function too.
830 $this->assertFalse(forum_is_subscribed($author->id, $forum));
831 $this->assertEquals(1, count($this->getDebuggingMessages()));
832 $this->resetDebugging();
834 // But subscribed to the discussion.
835 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($author->id, $forum, $discussion->id));
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,
843 // Now unsubscribe the user again from the discussion.
844 \mod_forum\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion);
846 // Check that the user is still unsubscribed from the forum.
847 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
849 // Check the deprecated function too.
850 $this->assertFalse(forum_is_subscribed($author->id, $forum));
851 $this->assertEquals(1, count($this->getDebuggingMessages()));
852 $this->resetDebugging();
854 // And is unsubscribed from the discussion again.
855 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum, $discussion->id));
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,
863 // And subscribe the user again to the discussion.
864 \mod_forum\subscriptions::subscribe_user_to_discussion($author->id, $discussion);
866 // Check that the user is still unsubscribed from the forum.
867 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
869 // Check the deprecated function too.
870 $this->assertFalse(forum_is_subscribed($author->id, $forum));
871 $this->assertEquals(1, count($this->getDebuggingMessages()));
872 $this->resetDebugging();
874 // And is subscribed to the discussion again.
875 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($author->id, $forum, $discussion->id));
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,
883 // And unsubscribe again.
884 \mod_forum\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion);
886 // Check that the user is still unsubscribed from the forum.
887 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum));
889 // Check the deprecated function too.
890 $this->assertFalse(forum_is_subscribed($author->id, $forum));
891 $this->assertEquals(1, count($this->getDebuggingMessages()));
892 $this->resetDebugging();
894 // But unsubscribed from the discussion.
895 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($author->id, $forum, $discussion->id));
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,
905 * Test that the deprecated forum_is_subscribed accepts numeric forum IDs.
907 public function test_forum_is_subscribed_numeric() {
910 $this->resetAfterTest(true);
912 // Create a course, with a forum.
913 $course = $this->getDataGenerator()->create_course();
915 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_CHOOSESUBSCRIBE);
916 $forum = $this->getDataGenerator()->create_module('forum', $options);
918 // Create a user enrolled in the course as a students.
919 list($author) = $this->helper_create_users($course, 1);
921 // Check that the user is currently unsubscribed to the forum.
922 $this->assertFalse(forum_is_subscribed($author->id, $forum->id));
923 $this->assertEquals(1, count($this->getDebuggingMessages()));
924 $this->resetDebugging();
926 // It should match the result of when it's called with the forum object.
927 $this->assertFalse(forum_is_subscribed($author->id, $forum));
928 $this->assertEquals(1, count($this->getDebuggingMessages()));
929 $this->resetDebugging();
931 // And when the user is subscribed, we should also get the correct result.
932 \mod_forum\subscriptions::subscribe_user($author->id, $forum);
934 $this->assertTrue(forum_is_subscribed($author->id, $forum->id));
935 $this->assertEquals(1, count($this->getDebuggingMessages()));
936 $this->resetDebugging();
938 // It should match the result of when it's called with the forum object.
939 $this->assertTrue(forum_is_subscribed($author->id, $forum));
940 $this->assertEquals(1, count($this->getDebuggingMessages()));
941 $this->resetDebugging();
945 * Test that the correct users are returned when fetching subscribed users from a forum where users can choose to
946 * subscribe and unsubscribe.
948 public function test_fetch_subscribed_users_subscriptions() {
951 $this->resetAfterTest(true);
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);
958 // Create some user enrolled in the course as a student.
960 $users = $this->helper_create_users($course, $usercount);
962 // All users should be subscribed.
963 $subscribers = \mod_forum\subscriptions::fetch_subscribed_users($forum);
964 $this->assertEquals($usercount, count($subscribers));
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));
971 // Unsubscribe 2 users.
972 $unsubscribedcount = 2;
973 for ($i = 0; $i < $unsubscribedcount; $i++) {
974 \mod_forum\subscriptions::unsubscribe_user($users[$i]->id, $forum);
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));
983 * Test that the correct users are returned hwen fetching subscribed users from a forum where users are forcibly
986 public function test_fetch_subscribed_users_forced() {
989 $this->resetAfterTest(true);
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);
996 // Create some user enrolled in the course as a student.
998 $users = $this->helper_create_users($course, $usercount);
1000 // All users should be subscribed.
1001 $subscribers = \mod_forum\subscriptions::fetch_subscribed_users($forum);
1002 $this->assertEquals($usercount, count($subscribers));
1006 * Test that unusual combinations of discussion subscriptions do not affect the subscribed user list.
1008 public function test_fetch_subscribed_users_discussion_subscriptions() {
1011 $this->resetAfterTest(true);
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);
1018 // Create some user enrolled in the course as a student.
1020 $users = $this->helper_create_users($course, $usercount);
1022 list($discussion, $post) = $this->helper_post_to_forum($forum, $users[0]);
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));
1030 \mod_forum\subscriptions::unsubscribe_user_from_discussion($users[0]->id, $discussion);
1032 // All users should be subscribed.
1033 $subscribers = \mod_forum\subscriptions::fetch_subscribed_users($forum);
1034 $this->assertEquals($usercount, count($subscribers));
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));
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;
1045 $record->preference = time();
1046 $DB->insert_record('forum_discussion_subs', $record);
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));
1054 // Unsubscribe 2 users.
1055 $unsubscribedcount = 2;
1056 for ($i = 0; $i < $unsubscribedcount; $i++) {
1057 \mod_forum\subscriptions::unsubscribe_user($users[$i]->id, $forum);
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));
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);
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));
1078 * Test whether a user is force-subscribed to a forum.
1080 public function test_force_subscribed_to_forum() {
1083 $this->resetAfterTest(true);
1085 // Create a course, with a forum.
1086 $course = $this->getDataGenerator()->create_course();
1088 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_FORCESUBSCRIBE);
1089 $forum = $this->getDataGenerator()->create_module('forum', $options);
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']);
1096 // Check that the user is currently subscribed to the forum.
1097 $this->assertTrue(\mod_forum\subscriptions::is_subscribed($user->id, $forum));
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));
1106 // Check that the user is no longer subscribed to the forum.
1107 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($user->id, $forum));
1111 * Test that the subscription cache can be pre-filled.
1113 public function test_subscription_cache_prefill() {
1116 $this->resetAfterTest(true);
1118 // Create a course, with a forum.
1119 $course = $this->getDataGenerator()->create_course();
1121 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_INITIALSUBSCRIBE);
1122 $forum = $this->getDataGenerator()->create_module('forum', $options);
1124 // Create some users.
1125 $users = $this->helper_create_users($course, 20);
1127 // Reset the subscription cache.
1128 \mod_forum\subscriptions::reset_forum_cache();
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);
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));
1141 $finalcount = $DB->perf_get_reads();
1142 $this->assertEquals(0, $finalcount - $postfillcount);
1146 * Test that the subscription cache can filled user-at-a-time.
1148 public function test_subscription_cache_fill() {
1151 $this->resetAfterTest(true);
1153 // Create a course, with a forum.
1154 $course = $this->getDataGenerator()->create_course();
1156 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_INITIALSUBSCRIBE);
1157 $forum = $this->getDataGenerator()->create_module('forum', $options);
1159 // Create some users.
1160 $users = $this->helper_create_users($course, 20);
1162 // Reset the subscription cache.
1163 \mod_forum\subscriptions::reset_forum_cache();
1165 // Filling the subscription cache should only use a single query.
1166 $startcount = $DB->perf_get_reads();
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));
1172 $finalcount = $DB->perf_get_reads();
1173 $this->assertEquals(20, $finalcount - $startcount);
1177 * Test that the discussion subscription cache can filled course-at-a-time.
1179 public function test_discussion_subscription_cache_fill_for_course() {
1182 $this->resetAfterTest(true);
1184 // Create a course, with a forum.
1185 $course = $this->getDataGenerator()->create_course();
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);
1195 // Create some users and keep a reference to the first user.
1196 $users = $this->helper_create_users($course, 20);
1197 $user = reset($users);
1199 // Reset the subscription caches.
1200 \mod_forum\subscriptions::reset_forum_cache();
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);
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));
1220 $finalcount = $DB->perf_get_reads();
1221 $this->assertEquals(count($users), $finalcount - $postfillcount);
1225 * Test that the discussion subscription cache can be forcibly updated for a user.
1227 public function test_discussion_subscription_cache_prefill() {
1230 $this->resetAfterTest(true);
1232 // Create a course, with a forum.
1233 $course = $this->getDataGenerator()->create_course();
1235 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_INITIALSUBSCRIBE);
1236 $forum = $this->getDataGenerator()->create_module('forum', $options);
1238 // Create some users.
1239 $users = $this->helper_create_users($course, 20);
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;
1249 // Unsubscribe half the users from the half the discussions.
1252 foreach ($discussions as $data) {
1253 if ($forumcount % 2) {
1256 foreach ($users as $user) {
1257 if ($usercount % 2) {
1260 \mod_forum\subscriptions::unsubscribe_user_from_discussion($user->id, $discussion);
1266 // Reset the subscription caches.
1267 \mod_forum\subscriptions::reset_forum_cache();
1268 \mod_forum\subscriptions::reset_discussion_cache();
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);
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);
1282 $finalcount = $DB->perf_get_reads();
1283 $this->assertEquals(0, $finalcount - $postfillcount);
1287 * Test that the discussion subscription cache can filled user-at-a-time.
1289 public function test_discussion_subscription_cache_fill() {
1292 $this->resetAfterTest(true);
1294 // Create a course, with a forum.
1295 $course = $this->getDataGenerator()->create_course();
1297 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_INITIALSUBSCRIBE);
1298 $forum = $this->getDataGenerator()->create_module('forum', $options);
1300 // Create some users.
1301 $users = $this->helper_create_users($course, 20);
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;
1311 // Unsubscribe half the users from the half the discussions.
1314 foreach ($discussions as $data) {
1315 if ($forumcount % 2) {
1318 foreach ($users as $user) {
1319 if ($usercount % 2) {
1322 \mod_forum\subscriptions::unsubscribe_user_from_discussion($user->id, $discussion);
1328 // Reset the subscription caches.
1329 \mod_forum\subscriptions::reset_forum_cache();
1330 \mod_forum\subscriptions::reset_discussion_cache();
1332 $startcount = $DB->perf_get_reads();
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);
1340 $finalcount = $DB->perf_get_reads();
1341 $this->assertEquals(20, $finalcount - $startcount);
1345 * Test that after toggling the forum subscription as another user,
1346 * the discussion subscription functionality works as expected.
1348 public function test_forum_subscribe_toggle_as_other_repeat_subscriptions() {
1351 $this->resetAfterTest(true);
1353 // Create a course, with a forum.
1354 $course = $this->getDataGenerator()->create_course();
1356 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_CHOOSESUBSCRIBE);
1357 $forum = $this->getDataGenerator()->create_module('forum', $options);
1359 // Create a user enrolled in the course as a student.
1360 list($user) = $this->helper_create_users($course, 1);
1362 // Post a discussion to the forum.
1363 list($discussion, $post) = $this->helper_post_to_forum($forum, $user);
1365 // Confirm that the user is currently not subscribed to the forum.
1366 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($user->id, $forum));
1368 // Confirm that the user is unsubscribed from the discussion too.
1369 $this->assertFalse(\mod_forum\subscriptions::is_subscribed($user->id, $forum, $discussion->id));
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,
1376 $this->assertEquals(0, $DB->count_records('forum_discussion_subs', array(
1377 'userid' => $user->id,
1378 'discussion' => $discussion->id,
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,
1388 $this->assertEquals(0, $DB->count_records('forum_discussion_subs', array(
1389 'userid' => $user->id,
1390 'discussion' => $discussion->id,
1393 // Now unsubscribe from the discussion. This should return true.
1394 $this->assertTrue(\mod_forum\subscriptions::unsubscribe_user_from_discussion($user->id, $discussion));
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));
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));
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));
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));
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);
1411 $this->assertEquals(0, $DB->count_records('forum_subscriptions', array(
1412 'userid' => $user->id,
1413 'forum' => $forum->id,
1415 $this->assertEquals(1, $DB->count_records('forum_discussion_subs', array(
1416 'userid' => $user->id,
1417 'discussion' => $discussion->id,
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,
1426 $this->assertEquals(1, $DB->count_records('forum_discussion_subs', array(
1427 'userid' => $user->id,
1428 'discussion' => $discussion->id,
1433 * Test that providing a context_module instance to is_subscribed does not result in additional lookups to retrieve
1434 * the context_module.
1436 public function test_is_subscribed_cm() {
1439 $this->resetAfterTest(true);
1441 // Create a course, with a forum.
1442 $course = $this->getDataGenerator()->create_course();
1444 $options = array('course' => $course->id, 'forcesubscribe' => FORUM_FORCESUBSCRIBE);
1445 $forum = $this->getDataGenerator()->create_module('forum', $options);
1447 // Create a user enrolled in the course as a student.
1448 list($user) = $this->helper_create_users($course, 1);
1450 // Retrieve the $cm now.
1451 $cm = get_fast_modinfo($forum->course)->instances['forum'][$forum->id];
1453 // Reset get_fast_modinfo.
1454 get_fast_modinfo(0, 0, true);
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));
1461 // Make a note of the number of DB calls.
1462 $basecount = $DB->perf_get_reads();
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));
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;
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;
1477 // There should be more queries than when we performed the same check a moment ago.
1478 $this->assertGreaterThan($suppliedcmcount, $calculatedcmcount);