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