[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/mod/forum/tests/ -> subscriptions_test.php (source)

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


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1