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