Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.2.x will end 22 April 2024 (12 months).
  • Bug fixes for security issues in 4.2.x will end 7 October 2024 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.1.x is supported too.

Differences Between: [Versions 310 and 402] [Versions 311 and 402] [Versions 39 and 402] [Versions 400 and 402] [Versions 401 and 402]

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