Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.0.x will end 8 May 2023 (12 months).
  • Bug fixes for security issues in 4.0.x will end 13 November 2023 (18 months).
  • PHP version: minimum PHP 7.3.0 Note: the minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is also supported.

Differences Between: [Versions 310 and 400] [Versions 39 and 400] [Versions 400 and 402] [Versions 400 and 403]

   1  <?php
   2  
   3  // This file is part of Moodle - http://moodle.org/
   4  //
   5  // Moodle is free software: you can redistribute it and/or modify
   6  // it under the terms of the GNU General Public License as published by
   7  // the Free Software Foundation, either version 3 of the License, or
   8  // (at your option) any later version.
   9  //
  10  // Moodle is distributed in the hope that it will be useful,
  11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13  // GNU General Public License for more details.
  14  //
  15  // You should have received a copy of the GNU General Public License
  16  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  17  
  18  namespace mod_forum;
  19  
  20  use mod_forum_tests_cron_trait;
  21  use mod_forum_tests_generator_trait;
  22  
  23  defined('MOODLE_INTERNAL') || die;
  24  
  25  require_once (__DIR__ . '/cron_trait.php');
  26  require_once (__DIR__ . '/generator_trait.php');
  27  
  28  /**
  29   * The module forums external functions unit tests
  30   *
  31   * @package    mod_forum
  32   * @category   test
  33   * @copyright  2013 Andrew Nicols
  34   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  35   */
  36  class maildigest_test extends \advanced_testcase {
  37  
  38      // Make use of the cron tester trait.
  39      use mod_forum_tests_cron_trait;
  40  
  41      // Make use of the test generator trait.
  42      use mod_forum_tests_generator_trait;
  43  
  44      /**
  45       * Set up message and mail sinks, and set up other requirements for the
  46       * cron to be tested here.
  47       */
  48      public function setUp(): void {
  49          global $CFG;
  50  
  51          // Messaging is not compatible with transactions...
  52          $this->preventResetByRollback();
  53  
  54          // Catch all messages
  55          $this->messagesink = $this->redirectMessages();
  56          $this->mailsink = $this->redirectEmails();
  57  
  58          // Confirm that we have an empty message sink so far.
  59          $messages = $this->messagesink->get_messages();
  60          $this->assertEquals(0, count($messages));
  61  
  62          $messages = $this->mailsink->get_messages();
  63          $this->assertEquals(0, count($messages));
  64  
  65          // Tell Moodle that we've not sent any digest messages out recently.
  66          $CFG->digestmailtimelast = 0;
  67  
  68          // And set the digest sending time to a negative number - this has
  69          // the effect of making it 11pm the previous day.
  70          $CFG->digestmailtime = -1;
  71  
  72          // Forcibly reduce the maxeditingtime to a one second to ensure that
  73          // messages are sent out.
  74          $CFG->maxeditingtime = 1;
  75  
  76          // We must clear the subscription caches. This has to be done both before each test, and after in case of other
  77          // tests using these functions.
  78          \mod_forum\subscriptions::reset_forum_cache();
  79          \mod_forum\subscriptions::reset_discussion_cache();
  80      }
  81  
  82      /**
  83       * Clear the message sinks set up in this test.
  84       */
  85      public function tearDown(): void {
  86          $this->messagesink->clear();
  87          $this->messagesink->close();
  88  
  89          $this->mailsink->clear();
  90          $this->mailsink->close();
  91      }
  92  
  93      /**
  94       * Setup a user, course, and forums.
  95       *
  96       * @return stdClass containing the list of forums, courses, forumids,
  97       * and the user enrolled in them.
  98       */
  99      protected function helper_setup_user_in_course() {
 100          global $DB;
 101  
 102          $return = new \stdClass();
 103          $return->courses = new \stdClass();
 104          $return->forums = new \stdClass();
 105          $return->forumids = array();
 106  
 107          // Create a user.
 108          $user = $this->getDataGenerator()->create_user();
 109          $return->user = $user;
 110  
 111          // Create courses to add the modules.
 112          $return->courses->course1 = $this->getDataGenerator()->create_course();
 113  
 114          // Create forums.
 115          $record = new \stdClass();
 116          $record->course = $return->courses->course1->id;
 117          $record->forcesubscribe = 1;
 118  
 119          $return->forums->forum1 = $this->getDataGenerator()->create_module('forum', $record);
 120          $return->forumsids[] = $return->forums->forum1->id;
 121  
 122          $return->forums->forum2 = $this->getDataGenerator()->create_module('forum', $record);
 123          $return->forumsids[] = $return->forums->forum2->id;
 124  
 125          // Check the forum was correctly created.
 126          list ($test, $params) = $DB->get_in_or_equal($return->forumsids);
 127  
 128          // Enrol the user in the courses.
 129          // DataGenerator->enrol_user automatically sets a role for the user
 130          $this->getDataGenerator()->enrol_user($return->user->id, $return->courses->course1->id);
 131  
 132          return $return;
 133      }
 134  
 135      public function test_set_maildigest() {
 136          global $DB;
 137  
 138          $this->resetAfterTest(true);
 139  
 140          $helper = $this->helper_setup_user_in_course();
 141          $user = $helper->user;
 142          $course1 = $helper->courses->course1;
 143          $forum1 = $helper->forums->forum1;
 144  
 145          // Set to the user.
 146          self::setUser($helper->user);
 147  
 148          // Confirm that there is no current value.
 149          $currentsetting = $DB->get_record('forum_digests', array(
 150              'forum' => $forum1->id,
 151              'userid' => $user->id,
 152          ));
 153          $this->assertFalse($currentsetting);
 154  
 155          // Test with each of the valid values:
 156          // 0, 1, and 2 are valid values.
 157          forum_set_user_maildigest($forum1, 0, $user);
 158          $currentsetting = $DB->get_record('forum_digests', array(
 159              'forum' => $forum1->id,
 160              'userid' => $user->id,
 161          ));
 162          $this->assertEquals($currentsetting->maildigest, 0);
 163  
 164          forum_set_user_maildigest($forum1, 1, $user);
 165          $currentsetting = $DB->get_record('forum_digests', array(
 166              'forum' => $forum1->id,
 167              'userid' => $user->id,
 168          ));
 169          $this->assertEquals($currentsetting->maildigest, 1);
 170  
 171          forum_set_user_maildigest($forum1, 2, $user);
 172          $currentsetting = $DB->get_record('forum_digests', array(
 173              'forum' => $forum1->id,
 174              'userid' => $user->id,
 175          ));
 176          $this->assertEquals($currentsetting->maildigest, 2);
 177  
 178          // And the default value - this should delete the record again
 179          forum_set_user_maildigest($forum1, -1, $user);
 180          $currentsetting = $DB->get_record('forum_digests', array(
 181              'forum' => $forum1->id,
 182              'userid' => $user->id,
 183          ));
 184          $this->assertFalse($currentsetting);
 185  
 186          // Try with an invalid value.
 187          $this->expectException('moodle_exception');
 188          forum_set_user_maildigest($forum1, 42, $user);
 189      }
 190  
 191      public function test_get_user_digest_options_default() {
 192          global $USER, $DB;
 193  
 194          $this->resetAfterTest(true);
 195  
 196          // Set up a basic user enrolled in a course.
 197          $helper = $this->helper_setup_user_in_course();
 198          $user = $helper->user;
 199          $course1 = $helper->courses->course1;
 200          $forum1 = $helper->forums->forum1;
 201  
 202          // Set to the user.
 203          self::setUser($helper->user);
 204  
 205          // We test against these options.
 206          $digestoptions = array(
 207              '0' => get_string('emaildigestoffshort', 'mod_forum'),
 208              '1' => get_string('emaildigestcompleteshort', 'mod_forum'),
 209              '2' => get_string('emaildigestsubjectsshort', 'mod_forum'),
 210          );
 211  
 212          // The default settings is 0.
 213          $this->assertEquals(0, $user->maildigest);
 214          $options = forum_get_user_digest_options();
 215          $this->assertEquals($options[-1], get_string('emaildigestdefault', 'mod_forum', $digestoptions[0]));
 216  
 217          // Update the setting to 1.
 218          $USER->maildigest = 1;
 219          $this->assertEquals(1, $USER->maildigest);
 220          $options = forum_get_user_digest_options();
 221          $this->assertEquals($options[-1], get_string('emaildigestdefault', 'mod_forum', $digestoptions[1]));
 222  
 223          // Update the setting to 2.
 224          $USER->maildigest = 2;
 225          $this->assertEquals(2, $USER->maildigest);
 226          $options = forum_get_user_digest_options();
 227          $this->assertEquals($options[-1], get_string('emaildigestdefault', 'mod_forum', $digestoptions[2]));
 228      }
 229  
 230      public function test_get_user_digest_options_sorting() {
 231          global $USER, $DB;
 232  
 233          $this->resetAfterTest(true);
 234  
 235          // Set up a basic user enrolled in a course.
 236          $helper = $this->helper_setup_user_in_course();
 237          $user = $helper->user;
 238          $course1 = $helper->courses->course1;
 239          $forum1 = $helper->forums->forum1;
 240  
 241          // Set to the user.
 242          self::setUser($helper->user);
 243  
 244          // Retrieve the list of applicable options.
 245          $options = forum_get_user_digest_options();
 246  
 247          // The default option must always be at the top of the list.
 248          $lastoption = -2;
 249          foreach ($options as $value => $description) {
 250              $this->assertGreaterThan($lastoption, $value);
 251              $lastoption = $value;
 252          }
 253      }
 254  
 255      public function test_cron_no_posts() {
 256          global $DB;
 257  
 258          $this->resetAfterTest(true);
 259  
 260          // Initially the forum cron should generate no messages as we've made no posts.
 261          $expect = [];
 262          $this->queue_tasks_and_assert($expect);
 263      }
 264  
 265      /**
 266       * Sends several notifications to one user as:
 267       * * single messages based on a user profile setting.
 268       */
 269      public function test_cron_profile_single_mails() {
 270          global $DB;
 271  
 272          $this->resetAfterTest(true);
 273  
 274          // Set up a basic user enrolled in a course.
 275          $userhelper = $this->helper_setup_user_in_course();
 276          $user = $userhelper->user;
 277          $course1 = $userhelper->courses->course1;
 278          $forum1 = $userhelper->forums->forum1;
 279          $forum2 = $userhelper->forums->forum2;
 280  
 281          // Add 5 discussions to forum 1.
 282          $posts = [];
 283          for ($i = 0; $i < 5; $i++) {
 284              list($discussion, $post) = $this->helper_post_to_forum($forum1, $user, ['mailnow' => 1]);
 285              $posts[] = $post;
 286          }
 287  
 288          // Add 5 discussions to forum 2.
 289          for ($i = 0; $i < 5; $i++) {
 290              list($discussion, $post) = $this->helper_post_to_forum($forum2, $user, ['mailnow' => 1]);
 291              $posts[] = $post;
 292          }
 293  
 294          // Set the tested user's default maildigest setting.
 295          $DB->set_field('user', 'maildigest', 0, array('id' => $user->id));
 296  
 297          // Set the maildigest preference for forum1 to default.
 298          forum_set_user_maildigest($forum1, -1, $user);
 299  
 300          // Set the maildigest preference for forum2 to default.
 301          forum_set_user_maildigest($forum2, -1, $user);
 302  
 303          // No digests mails should be sent, but 10 forum mails will be sent.
 304          $expect = [
 305              (object) [
 306                  'userid' => $user->id,
 307                  'messages' => 10,
 308                  'digests' => 0,
 309              ],
 310          ];
 311          $this->queue_tasks_and_assert($expect);
 312  
 313          $this->send_notifications_and_assert($user, $posts);
 314      }
 315  
 316      /**
 317       * Sends several notifications to one user as:
 318       * * daily digests coming from the user profile setting.
 319       */
 320      public function test_cron_profile_digest_email() {
 321          global $DB, $CFG;
 322  
 323          $this->resetAfterTest(true);
 324  
 325          // Set up a basic user enrolled in a course.
 326          $userhelper = $this->helper_setup_user_in_course();
 327          $user = $userhelper->user;
 328          $course1 = $userhelper->courses->course1;
 329          $forum1 = $userhelper->forums->forum1;
 330          $forum2 = $userhelper->forums->forum2;
 331          $posts = [];
 332  
 333          // Add 5 discussions to forum 1.
 334          for ($i = 0; $i < 5; $i++) {
 335              list($discussion, $post) = $this->helper_post_to_forum($forum1, $user, ['mailnow' => 1]);
 336              $posts[] = $post;
 337          }
 338  
 339          // Add 5 discussions to forum 2.
 340          for ($i = 0; $i < 5; $i++) {
 341              list($discussion, $post) = $this->helper_post_to_forum($forum2, $user, ['mailnow' => 1]);
 342              $posts[] = $post;
 343          }
 344  
 345          // Set the tested user's default maildigest setting.
 346          $DB->set_field('user', 'maildigest', 1, array('id' => $user->id));
 347  
 348          // Set the maildigest preference for forum1 to default.
 349          forum_set_user_maildigest($forum1, -1, $user);
 350  
 351          // Set the maildigest preference for forum2 to default.
 352          forum_set_user_maildigest($forum2, -1, $user);
 353  
 354          // No digests mails should be sent, but 10 forum mails will be sent.
 355          $expect = [
 356              (object) [
 357                  'userid' => $user->id,
 358                  'messages' => 0,
 359                  'digests' => 1,
 360              ],
 361          ];
 362          $this->queue_tasks_and_assert($expect);
 363  
 364          $this->send_digests_and_assert($user, $posts);
 365      }
 366  
 367      /**
 368       * Send digests to a user who cannot view fullnames
 369       */
 370      public function test_cron_digest_view_fullnames_off() {
 371          global $DB, $CFG;
 372  
 373          $CFG->fullnamedisplay = 'lastname';
 374          $this->resetAfterTest(true);
 375  
 376          // Set up a basic user enrolled in a course.
 377          $userhelper = $this->helper_setup_user_in_course();
 378          $user = $userhelper->user;
 379          $course1 = $userhelper->courses->course1;
 380          $forum1 = $userhelper->forums->forum1;
 381          $posts = [];
 382  
 383          // Add 1 discussions to forum 1.
 384          list($discussion, $post) = $this->helper_post_to_forum($forum1, $user, ['mailnow' => 1]);
 385          $posts[] = $post;
 386  
 387          // Set the tested user's default maildigest setting.
 388          $DB->set_field('user', 'maildigest', 1, array('id' => $user->id));
 389  
 390          // No digests mails should be sent, but 1 forum mails will be sent.
 391          $expect = [
 392              (object) [
 393                  'userid' => $user->id,
 394                  'messages' => 0,
 395                  'digests' => 1,
 396              ],
 397          ];
 398          $this->queue_tasks_and_assert($expect);
 399          $this->send_digests_and_assert($user, $posts);
 400  
 401          // The user does not, by default, have permission to view the fullname.
 402          $messagecontent = $this->messagesink->get_messages()[0]->fullmessage;
 403  
 404          // Assert that the expected name is present (lastname only).
 405          $this->assertStringContainsString(fullname($user, false), $messagecontent);
 406  
 407          // Assert that the full name is not present (firstname lastname only).
 408          $this->assertStringNotContainsString(fullname($user, true), $messagecontent);
 409      }
 410  
 411      /**
 412       * Send digests to a user who can view fullnames.
 413       */
 414      public function test_cron_digest_view_fullnames_on() {
 415          global $DB, $CFG;
 416  
 417          $CFG->fullnamedisplay = 'lastname';
 418          $this->resetAfterTest(true);
 419  
 420          // Set up a basic user enrolled in a course.
 421          $userhelper = $this->helper_setup_user_in_course();
 422          $user = $userhelper->user;
 423          $course1 = $userhelper->courses->course1;
 424          $forum1 = $userhelper->forums->forum1;
 425          $posts = [];
 426          assign_capability(
 427              'moodle/site:viewfullnames',
 428              CAP_ALLOW,
 429              $DB->get_field('role', 'id', ['shortname' => 'student']),
 430              \context_course::instance($course1->id)
 431          );
 432  
 433          // Add 1 discussions to forum 1.
 434          list($discussion, $post) = $this->helper_post_to_forum($forum1, $user, ['mailnow' => 1]);
 435          $posts[] = $post;
 436  
 437          // Set the tested user's default maildigest setting.
 438          $DB->set_field('user', 'maildigest', 1, array('id' => $user->id));
 439  
 440          // No digests mails should be sent, but 1 forum mails will be sent.
 441          $expect = [
 442              (object) [
 443                  'userid' => $user->id,
 444                  'messages' => 0,
 445                  'digests' => 1,
 446              ],
 447          ];
 448          $this->queue_tasks_and_assert($expect);
 449          $this->send_digests_and_assert($user, $posts);
 450  
 451          // The user does not, by default, have permission to view the fullname.
 452          // However we have given the user that capability so we expect to see both firstname and lastname.
 453          $messagecontent = $this->messagesink->get_messages()[0]->fullmessage;
 454  
 455          // Assert that the expected name is present (lastname only).
 456          $this->assertStringContainsString(fullname($user, false), $messagecontent);
 457  
 458          // Assert that the full name is also present (firstname lastname only).
 459          $this->assertStringContainsString(fullname($user, true), $messagecontent);
 460      }
 461  
 462      /**
 463       * Sends several notifications to one user as:
 464       * * daily digests coming from the per-forum setting; and
 465       * * single e-mails from the profile setting.
 466       */
 467      public function test_cron_mixed_email_1() {
 468          global $DB, $CFG;
 469  
 470          $this->resetAfterTest(true);
 471  
 472          // Set up a basic user enrolled in a course.
 473          $userhelper = $this->helper_setup_user_in_course();
 474          $user = $userhelper->user;
 475          $course1 = $userhelper->courses->course1;
 476          $forum1 = $userhelper->forums->forum1;
 477          $forum2 = $userhelper->forums->forum2;
 478          $posts = [];
 479          $digests = [];
 480  
 481          // Add 5 discussions to forum 1.
 482          for ($i = 0; $i < 5; $i++) {
 483              list($discussion, $post) = $this->helper_post_to_forum($forum1, $user, ['mailnow' => 1]);
 484              $digests[] = $post;
 485          }
 486  
 487          // Add 5 discussions to forum 2.
 488          for ($i = 0; $i < 5; $i++) {
 489              list($discussion, $post) = $this->helper_post_to_forum($forum2, $user, ['mailnow' => 1]);
 490              $posts[] = $post;
 491          }
 492  
 493          // Set the tested user's default maildigest setting.
 494          $DB->set_field('user', 'maildigest', 0, array('id' => $user->id));
 495  
 496          // Set the maildigest preference for forum1 to digest.
 497          forum_set_user_maildigest($forum1, 1, $user);
 498  
 499          // Set the maildigest preference for forum2 to default (single).
 500          forum_set_user_maildigest($forum2, -1, $user);
 501  
 502          // One digest e-mail should be sent, and five individual notifications.
 503          $expect = [
 504              (object) [
 505                  'userid' => $user->id,
 506                  'messages' => 5,
 507                  'digests' => 1,
 508              ],
 509          ];
 510          $this->queue_tasks_and_assert($expect);
 511  
 512          $this->send_notifications_and_assert($user, $posts);
 513          $this->send_digests_and_assert($user, $digests);
 514      }
 515  
 516      /**
 517       * Sends several notifications to one user as:
 518       * * single e-mails from the per-forum setting; and
 519       * * daily digests coming from the per-user setting.
 520       */
 521      public function test_cron_mixed_email_2() {
 522          global $DB, $CFG;
 523  
 524          $this->resetAfterTest(true);
 525  
 526          // Set up a basic user enrolled in a course.
 527          $userhelper = $this->helper_setup_user_in_course();
 528          $user = $userhelper->user;
 529          $course1 = $userhelper->courses->course1;
 530          $forum1 = $userhelper->forums->forum1;
 531          $forum2 = $userhelper->forums->forum2;
 532          $posts = [];
 533          $digests = [];
 534  
 535          // Add 5 discussions to forum 1.
 536          for ($i = 0; $i < 5; $i++) {
 537              list($discussion, $post) = $this->helper_post_to_forum($forum1, $user, ['mailnow' => 1]);
 538              $digests[] = $post;
 539          }
 540  
 541          // Add 5 discussions to forum 2.
 542          for ($i = 0; $i < 5; $i++) {
 543              list($discussion, $post) = $this->helper_post_to_forum($forum2, $user, ['mailnow' => 1]);
 544              $posts[] = $post;
 545          }
 546  
 547          // Set the tested user's default maildigest setting.
 548          $DB->set_field('user', 'maildigest', 1, array('id' => $user->id));
 549  
 550          // Set the maildigest preference for forum1 to digest.
 551          forum_set_user_maildigest($forum1, -1, $user);
 552  
 553          // Set the maildigest preference for forum2 to single.
 554          forum_set_user_maildigest($forum2, 0, $user);
 555  
 556          // One digest e-mail should be sent, and five individual notifications.
 557          $expect = [
 558              (object) [
 559                  'userid' => $user->id,
 560                  'messages' => 5,
 561                  'digests' => 1,
 562              ],
 563          ];
 564          $this->queue_tasks_and_assert($expect);
 565  
 566          $this->send_notifications_and_assert($user, $posts);
 567          $this->send_digests_and_assert($user, $digests);
 568      }
 569  
 570      /**
 571       * Sends several notifications to one user as:
 572       * * daily digests coming from the per-forum setting.
 573       */
 574      public function test_cron_forum_digest_email() {
 575          global $DB, $CFG;
 576  
 577          $this->resetAfterTest(true);
 578  
 579          // Set up a basic user enrolled in a course.
 580          $userhelper = $this->helper_setup_user_in_course();
 581          $user = $userhelper->user;
 582          $course1 = $userhelper->courses->course1;
 583          $forum1 = $userhelper->forums->forum1;
 584          $forum2 = $userhelper->forums->forum2;
 585          $fulldigests = [];
 586          $shortdigests = [];
 587  
 588          // Add 5 discussions to forum 1.
 589          for ($i = 0; $i < 5; $i++) {
 590              list($discussion, $post) = $this->helper_post_to_forum($forum1, $user, ['mailnow' => 1]);
 591              $fulldigests[] = $post;
 592          }
 593  
 594          // Add 5 discussions to forum 2.
 595          for ($i = 0; $i < 5; $i++) {
 596              list($discussion, $post) = $this->helper_post_to_forum($forum2, $user, ['mailnow' => 1]);
 597              $shortdigests[] = $post;
 598          }
 599  
 600          // Set the tested user's default maildigest setting.
 601          $DB->set_field('user', 'maildigest', 0, array('id' => $user->id));
 602  
 603          // Set the maildigest preference for forum1 to digest (complete).
 604          forum_set_user_maildigest($forum1, 1, $user);
 605  
 606          // Set the maildigest preference for forum2 to digest (short).
 607          forum_set_user_maildigest($forum2, 2, $user);
 608  
 609          // One digest e-mail should be sent, and no individual notifications.
 610          $expect = [
 611              (object) [
 612                  'userid' => $user->id,
 613                  'digests' => 1,
 614              ],
 615          ];
 616          $this->queue_tasks_and_assert($expect);
 617  
 618          $this->send_digests_and_assert($user, $fulldigests, $shortdigests);
 619      }
 620  
 621      /**
 622       * The digest being in the past is queued til the next day.
 623       */
 624      public function test_cron_digest_previous_day() {
 625          global $DB, $CFG;
 626  
 627          $this->resetAfterTest(true);
 628  
 629          // Set up a basic user enrolled in a course.
 630          $userhelper = $this->helper_setup_user_in_course();
 631          $user = $userhelper->user;
 632          $course1 = $userhelper->courses->course1;
 633          $forum1 = $userhelper->forums->forum1;
 634          $forum2 = $userhelper->forums->forum2;
 635          $fulldigests = [];
 636          $shortdigests = [];
 637  
 638          // Add 1 discussions to forum 1.
 639          list($discussion, $post) = $this->helper_post_to_forum($forum1, $user, ['mailnow' => 1]);
 640          $fulldigests[] = $post;
 641  
 642          // Set the tested user's default maildigest setting.
 643          $DB->set_field('user', 'maildigest', 1, array('id' => $user->id));
 644  
 645          // Set the digest time to midnight.
 646          $CFG->digestmailtime = 0;
 647          // One digest e-mail should be sent, and no individual notifications.
 648          $expect = [
 649              (object) [
 650                  'userid' => $user->id,
 651                  'digests' => 1,
 652              ],
 653          ];
 654          $this->queue_tasks_and_assert($expect);
 655  
 656          $tasks = $DB->get_records('task_adhoc', ['component' => 'mod_forum']);
 657          $task = reset($tasks);
 658          $this->assertGreaterThanOrEqual(time(), $task->nextruntime);
 659      }
 660  
 661      /**
 662       * The digest being in the future is queued for today.
 663       */
 664      public function test_cron_digest_same_day() {
 665          global $DB, $CFG;
 666  
 667          $this->resetAfterTest(true);
 668  
 669          // Set up a basic user enrolled in a course.
 670          $userhelper = $this->helper_setup_user_in_course();
 671          $user = $userhelper->user;
 672          $course1 = $userhelper->courses->course1;
 673          $forum1 = $userhelper->forums->forum1;
 674          $forum2 = $userhelper->forums->forum2;
 675          $fulldigests = [];
 676          $shortdigests = [];
 677  
 678          // Add 1 discussions to forum 1.
 679          list($discussion, $post) = $this->helper_post_to_forum($forum1, $user, ['mailnow' => 1]);
 680          $fulldigests[] = $post;
 681  
 682          // Set the tested user's default maildigest setting.
 683          $DB->set_field('user', 'maildigest', 1, array('id' => $user->id));
 684  
 685          // Set the digest time to the future (magic, shouldn't work).
 686          $CFG->digestmailtime = 25;
 687          // One digest e-mail should be sent, and no individual notifications.
 688          $expect = [
 689              (object) [
 690                  'userid' => $user->id,
 691                  'digests' => 1,
 692              ],
 693          ];
 694          $this->queue_tasks_and_assert($expect);
 695  
 696          $tasks = $DB->get_records('task_adhoc', ['component' => 'mod_forum']);
 697          $task = reset($tasks);
 698          $digesttime = usergetmidnight(time(), \core_date::get_server_timezone()) + ($CFG->digestmailtime * 3600);
 699          $this->assertLessThanOrEqual($digesttime, $task->nextruntime);
 700      }
 701  
 702      /**
 703       * Tests that if a new message is posted after the days digest time,
 704       * but before that days digests are sent a new task is created.
 705       */
 706      public function test_cron_digest_queue_next_before_current_processed() {
 707          global $DB, $CFG;
 708  
 709          $this->resetAfterTest(true);
 710  
 711          // Set up a basic user enrolled in a course.
 712          $userhelper = $this->helper_setup_user_in_course();
 713          $user = $userhelper->user;
 714          $forum1 = $userhelper->forums->forum1;
 715  
 716          // Add 1 discussions to forum 1.
 717          $this->helper_post_to_forum($forum1, $user, ['mailnow' => 1]);
 718  
 719          // Set the tested user's default maildigest setting.
 720          $DB->set_field('user', 'maildigest', 1, ['id' => $user->id]);
 721  
 722          // Set the digest time to the future (magic, shouldn't work).
 723          $CFG->digestmailtime = 25;
 724          // One digest e-mail should be sent, and no individual notifications.
 725          $expect = [
 726              (object) [
 727                  'userid' => $user->id,
 728                  'digests' => 1,
 729              ],
 730          ];
 731          $this->queue_tasks_and_assert($expect);
 732  
 733          // Set the digest time to midnight.
 734          $CFG->digestmailtime = 0;
 735  
 736          // Add another discussions to forum 1.
 737          $this->helper_post_to_forum($forum1, $user, ['mailnow' => 1]);
 738  
 739          // One digest e-mail should be sent, and no individual notifications.
 740          $expect = [
 741              (object) [
 742                  'userid' => $user->id,
 743                  'digests' => 1,
 744              ],
 745          ];
 746          $this->queue_tasks_and_assert($expect);
 747  
 748          // There should now be two tasks queued.
 749          $tasks = $DB->get_records('task_adhoc', ['component' => 'mod_forum']);
 750          $this->assertCount(2, $tasks);
 751  
 752          // Add yet another another discussions to forum 1.
 753          $this->helper_post_to_forum($forum1, $user, ['mailnow' => 1]);
 754  
 755          // One digest e-mail should be sent, and no individual notifications.
 756          $expect = [
 757              (object) [
 758                  'userid' => $user->id,
 759                  'digests' => 1,
 760              ],
 761          ];
 762          $this->queue_tasks_and_assert($expect);
 763  
 764          // There should still be two tasks queued.
 765          $tasks = $DB->get_records('task_adhoc', ['component' => 'mod_forum']);
 766          $this->assertCount(2, $tasks);
 767      }
 768  
 769      /**
 770       * The sending of a digest marks posts as read if automatic message read marking is set.
 771       */
 772      public function test_cron_digest_marks_posts_read() {
 773          global $DB, $CFG;
 774  
 775          $this->resetAfterTest(true);
 776  
 777          // Disable the 'Manual message read marking' option.
 778          $CFG->forum_usermarksread = false;
 779  
 780          // Set up a basic user enrolled in a course.
 781          $userhelper = $this->helper_setup_user_in_course();
 782          $user = $userhelper->user;
 783          $course1 = $userhelper->courses->course1;
 784          $forum1 = $userhelper->forums->forum1;
 785          $posts = [];
 786  
 787          // Set the tested user's default maildigest, trackforums, read tracking settings.
 788          $DB->set_field('user', 'maildigest', 1, ['id' => $user->id]);
 789          $DB->set_field('user', 'trackforums', 1, ['id' => $user->id]);
 790          set_user_preference('forum_markasreadonnotification', 1, $user->id);
 791  
 792          // Set the maildigest preference for forum1 to default.
 793          forum_set_user_maildigest($forum1, -1, $user);
 794  
 795          // Add 5 discussions to forum 1.
 796          for ($i = 0; $i < 5; $i++) {
 797              list($discussion, $post) = $this->helper_post_to_forum($forum1, $user, ['mailnow' => 1]);
 798              $posts[] = $post;
 799          }
 800  
 801          // There should be unread posts for the forum.
 802          $expectedposts = [
 803              $forum1->id => (object) [
 804                  'id' => $forum1->id,
 805                  'unread' => count($posts),
 806              ],
 807          ];
 808          $this->assertEquals($expectedposts, forum_tp_get_course_unread_posts($user->id, $course1->id));
 809  
 810          // One digest mail should be sent and no other messages.
 811          $expect = [
 812              (object) [
 813                  'userid' => $user->id,
 814                  'messages' => 0,
 815                  'digests' => 1,
 816              ],
 817          ];
 818          $this->queue_tasks_and_assert($expect);
 819  
 820          $this->send_digests_and_assert($user, $posts);
 821  
 822          // Verify that there are no unread posts for any forums.
 823          $this->assertEmpty(forum_tp_get_course_unread_posts($user->id, $course1->id));
 824      }
 825  
 826      /**
 827       * The sending of a digest does not mark posts as read when manual message read marking is set.
 828       */
 829      public function test_cron_digest_leaves_posts_unread() {
 830          global $DB, $CFG;
 831  
 832          $this->resetAfterTest(true);
 833  
 834          // Enable the 'Manual message read marking' option.
 835          $CFG->forum_usermarksread = true;
 836  
 837          // Set up a basic user enrolled in a course.
 838          $userhelper = $this->helper_setup_user_in_course();
 839          $user = $userhelper->user;
 840          $course1 = $userhelper->courses->course1;
 841          $forum1 = $userhelper->forums->forum1;
 842          $posts = [];
 843  
 844          // Set the tested user's default maildigest, trackforums, read tracking settings.
 845          $DB->set_field('user', 'maildigest', 1, ['id' => $user->id]);
 846          $DB->set_field('user', 'trackforums', 1, ['id' => $user->id]);
 847          set_user_preference('forum_markasreadonnotification', 1, $user->id);
 848  
 849          // Set the maildigest preference for forum1 to default.
 850          forum_set_user_maildigest($forum1, -1, $user);
 851  
 852          // Add 5 discussions to forum 1.
 853          for ($i = 0; $i < 5; $i++) {
 854              list($discussion, $post) = $this->helper_post_to_forum($forum1, $user, ['mailnow' => 1]);
 855              $posts[] = $post;
 856          }
 857  
 858          // There should be unread posts for the forum.
 859          $expectedposts = [
 860              $forum1->id => (object) [
 861                  'id' => $forum1->id,
 862                  'unread' => count($posts),
 863              ],
 864          ];
 865          $this->assertEquals($expectedposts, forum_tp_get_course_unread_posts($user->id, $course1->id));
 866  
 867          // One digest mail should be sent and no other messages.
 868          $expect = [
 869              (object) [
 870                  'userid' => $user->id,
 871                  'messages' => 0,
 872                  'digests' => 1,
 873              ],
 874          ];
 875          $this->queue_tasks_and_assert($expect);
 876  
 877          $this->send_digests_and_assert($user, $posts);
 878  
 879          // Verify that there are still the same unread posts for the forum.
 880          $this->assertEquals($expectedposts, forum_tp_get_course_unread_posts($user->id, $course1->id));
 881      }
 882  }