Merge branch 'MDL-53166' of https://github.com/eugeneventer/moodle-fixes
[moodle.git] / mod / forum / tests / maildigest_test.php
CommitLineData
0462b6a1
AN
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/**
19 * The module forums external functions unit tests
20 *
21 * @package mod_forum
22 * @category external
23 * @copyright 2013 Andrew Nicols
24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 */
26
27defined('MOODLE_INTERNAL') || die();
28
29global $CFG;
30
31class mod_forum_maildigest_testcase extends advanced_testcase {
32
908996b1
AN
33 /**
34 * Keep track of the message and mail sinks that we set up for each
35 * test.
36 *
37 * @var stdClass $helper
38 */
39 protected $helper;
40
41 /**
42 * Set up message and mail sinks, and set up other requirements for the
43 * cron to be tested here.
44 */
45 public function setUp() {
46 global $CFG;
47
48 $this->helper = new stdClass();
49
50 // Messaging is not compatible with transactions...
51 $this->preventResetByRollback();
52
53 // Catch all messages
54 $this->helper->messagesink = $this->redirectMessages();
55 $this->helper->mailsink = $this->redirectEmails();
56
57 // Confirm that we have an empty message sink so far.
58 $messages = $this->helper->messagesink->get_messages();
59 $this->assertEquals(0, count($messages));
60
61 $messages = $this->helper->mailsink->get_messages();
62 $this->assertEquals(0, count($messages));
63
64 // Tell Moodle that we've not sent any digest messages out recently.
65 $CFG->digestmailtimelast = 0;
66
67 // And set the digest sending time to a negative number - this has
68 // the effect of making it 11pm the previous day.
69 $CFG->digestmailtime = -1;
70
71 // Forcibly reduce the maxeditingtime to a one second to ensure that
72 // messages are sent out.
73 $CFG->maxeditingtime = 1;
74
a54702b2
AN
75 // We must clear the subscription caches. This has to be done both before each test, and after in case of other
76 // tests using these functions.
77 \mod_forum\subscriptions::reset_forum_cache();
78 \mod_forum\subscriptions::reset_discussion_cache();
908996b1 79 }
0462b6a1 80
908996b1
AN
81 /**
82 * Clear the message sinks set up in this test.
83 */
84 public function tearDown() {
85 $this->helper->messagesink->clear();
86 $this->helper->messagesink->close();
0462b6a1 87
908996b1
AN
88 $this->helper->mailsink->clear();
89 $this->helper->mailsink->close();
90 }
f79f3c00 91
908996b1
AN
92 /**
93 * Setup a user, course, and forums.
94 *
95 * @return stdClass containing the list of forums, courses, forumids,
96 * and the user enrolled in them.
97 */
98 protected function helper_setup_user_in_course() {
99 global $DB;
0462b6a1 100
908996b1
AN
101 $return = new stdClass();
102 $return->courses = new stdClass();
103 $return->forums = new stdClass();
104 $return->forumids = array();
105
106 // Create a user.
107 $user = $this->getDataGenerator()->create_user();
108 $return->user = $user;
f79f3c00 109
908996b1
AN
110 // Create courses to add the modules.
111 $return->courses->course1 = $this->getDataGenerator()->create_course();
0462b6a1 112
908996b1 113 // Create forums.
0462b6a1 114 $record = new stdClass();
908996b1
AN
115 $record->course = $return->courses->course1->id;
116 $record->forcesubscribe = 1;
0462b6a1 117
908996b1
AN
118 $return->forums->forum1 = $this->getDataGenerator()->create_module('forum', $record);
119 $return->forumsids[] = $return->forums->forum1->id;
0462b6a1 120
908996b1
AN
121 $return->forums->forum2 = $this->getDataGenerator()->create_module('forum', $record);
122 $return->forumsids[] = $return->forums->forum2->id;
123
124 // Check the forum was correctly created.
125 list ($test, $params) = $DB->get_in_or_equal($return->forumsids);
0462b6a1
AN
126
127 // Enrol the user in the courses.
128 // DataGenerator->enrol_user automatically sets a role for the user
908996b1
AN
129 $this->getDataGenerator()->enrol_user($return->user->id, $return->courses->course1->id);
130
131 return $return;
132 }
133
134 /**
135 * Helper to falsify all forum post records for a digest run.
136 */
137 protected function helper_force_digest_mail_times() {
138 global $CFG, $DB;
139 // Fake all of the post editing times because digests aren't sent until
140 // the start of an hour where the modification time on the message is before
141 // the start of that hour
d6e7a63d
PS
142 $sitetimezone = core_date::get_server_timezone();
143 $digesttime = usergetmidnight(time(), $sitetimezone) + ($CFG->digestmailtime * 3600) - (60 * 60);
908996b1
AN
144 $DB->set_field('forum_posts', 'modified', $digesttime, array('mailed' => 0));
145 $DB->set_field('forum_posts', 'created', $digesttime, array('mailed' => 0));
146 }
147
148 /**
149 * Run the forum cron, and check that the specified post was sent the
150 * specified number of times.
151 *
152 * @param integer $expected The number of times that the post should have been sent
00999605
AN
153 * @param integer $individualcount The number of individual messages sent
154 * @param integer $digestcount The number of digest messages sent
908996b1 155 */
00999605 156 protected function helper_run_cron_check_count($expected, $individualcount, $digestcount) {
908996b1
AN
157 if ($expected === 0) {
158 $this->expectOutputRegex('/(Email digests successfully sent to .* users.){0}/');
159 } else {
160 $this->expectOutputRegex("/Email digests successfully sent to {$expected} users/");
161 }
162 forum_cron();
163
164 // Now check the results in the message sink.
165 $messages = $this->helper->messagesink->get_messages();
908996b1 166
00999605
AN
167 $counts = (object) array('digest' => 0, 'individual' => 0);
168 foreach ($messages as $message) {
169 if (strpos($message->subject, 'forum digest') !== false) {
170 $counts->digest++;
171 } else {
172 $counts->individual++;
173 }
174 }
908996b1 175
00999605
AN
176 $this->assertEquals($digestcount, $counts->digest);
177 $this->assertEquals($individualcount, $counts->individual);
908996b1
AN
178 }
179
180 public function test_set_maildigest() {
181 global $DB;
182
183 $this->resetAfterTest(true);
184
185 $helper = $this->helper_setup_user_in_course();
186 $user = $helper->user;
187 $course1 = $helper->courses->course1;
188 $forum1 = $helper->forums->forum1;
189
190 // Set to the user.
191 self::setUser($helper->user);
0462b6a1
AN
192
193 // Confirm that there is no current value.
194 $currentsetting = $DB->get_record('forum_digests', array(
195 'forum' => $forum1->id,
196 'userid' => $user->id,
197 ));
198 $this->assertFalse($currentsetting);
199
200 // Test with each of the valid values:
201 // 0, 1, and 2 are valid values.
202 forum_set_user_maildigest($forum1, 0, $user);
203 $currentsetting = $DB->get_record('forum_digests', array(
204 'forum' => $forum1->id,
205 'userid' => $user->id,
206 ));
207 $this->assertEquals($currentsetting->maildigest, 0);
208
209 forum_set_user_maildigest($forum1, 1, $user);
210 $currentsetting = $DB->get_record('forum_digests', array(
211 'forum' => $forum1->id,
212 'userid' => $user->id,
213 ));
214 $this->assertEquals($currentsetting->maildigest, 1);
215
216 forum_set_user_maildigest($forum1, 2, $user);
217 $currentsetting = $DB->get_record('forum_digests', array(
218 'forum' => $forum1->id,
219 'userid' => $user->id,
220 ));
221 $this->assertEquals($currentsetting->maildigest, 2);
222
223 // And the default value - this should delete the record again
224 forum_set_user_maildigest($forum1, -1, $user);
225 $currentsetting = $DB->get_record('forum_digests', array(
226 'forum' => $forum1->id,
227 'userid' => $user->id,
228 ));
229 $this->assertFalse($currentsetting);
230
231 // Try with an invalid value.
232 $this->setExpectedException('moodle_exception');
233 forum_set_user_maildigest($forum1, 42, $user);
234 }
235
908996b1 236 public function test_get_user_digest_options_default() {
0462b6a1
AN
237 global $USER, $DB;
238
239 $this->resetAfterTest(true);
240
908996b1
AN
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;
0462b6a1
AN
246
247 // Set to the user.
908996b1 248 self::setUser($helper->user);
0462b6a1
AN
249
250 // We test against these options.
251 $digestoptions = array(
252 '0' => get_string('emaildigestoffshort', 'mod_forum'),
253 '1' => get_string('emaildigestcompleteshort', 'mod_forum'),
254 '2' => get_string('emaildigestsubjectsshort', 'mod_forum'),
255 );
256
257 // The default settings is 0.
258 $this->assertEquals(0, $user->maildigest);
259 $options = forum_get_user_digest_options();
260 $this->assertEquals($options[-1], get_string('emaildigestdefault', 'mod_forum', $digestoptions[0]));
261
262 // Update the setting to 1.
263 $USER->maildigest = 1;
264 $this->assertEquals(1, $USER->maildigest);
265 $options = forum_get_user_digest_options();
266 $this->assertEquals($options[-1], get_string('emaildigestdefault', 'mod_forum', $digestoptions[1]));
267
268 // Update the setting to 2.
269 $USER->maildigest = 2;
270 $this->assertEquals(2, $USER->maildigest);
271 $options = forum_get_user_digest_options();
272 $this->assertEquals($options[-1], get_string('emaildigestdefault', 'mod_forum', $digestoptions[2]));
273 }
274
908996b1 275 public function test_get_user_digest_options_sorting() {
0462b6a1
AN
276 global $USER, $DB;
277
278 $this->resetAfterTest(true);
279
908996b1
AN
280 // Set up a basic user enrolled in a course.
281 $helper = $this->helper_setup_user_in_course();
282 $user = $helper->user;
283 $course1 = $helper->courses->course1;
284 $forum1 = $helper->forums->forum1;
0462b6a1
AN
285
286 // Set to the user.
908996b1 287 self::setUser($helper->user);
0462b6a1
AN
288
289 // Retrieve the list of applicable options.
290 $options = forum_get_user_digest_options();
291
292 // The default option must always be at the top of the list.
293 $lastoption = -2;
294 foreach ($options as $value => $description) {
295 $this->assertGreaterThan($lastoption, $value);
296 $lastoption = $value;
297 }
298 }
299
908996b1
AN
300 public function test_cron_no_posts() {
301 global $DB;
302
303 $this->resetAfterTest(true);
304
305 $this->helper_force_digest_mail_times();
306
307 // Initially the forum cron should generate no messages as we've made no posts.
308 $this->helper_run_cron_check_count(0, 0, 0);
309 }
310
311 /**
312 * Sends several notifications to one user as:
313 * * single messages based on a user profile setting.
314 */
315 public function test_cron_profile_single_mails() {
316 global $DB;
317
318 $this->resetAfterTest(true);
319
320 // Set up a basic user enrolled in a course.
321 $userhelper = $this->helper_setup_user_in_course();
322 $user = $userhelper->user;
323 $course1 = $userhelper->courses->course1;
324 $forum1 = $userhelper->forums->forum1;
325 $forum2 = $userhelper->forums->forum2;
326
327 // Add some discussions to the forums.
328 $record = new stdClass();
329 $record->course = $course1->id;
330 $record->userid = $user->id;
331 $record->mailnow = 1;
332
333 // Add 5 discussions to forum 1.
334 $record->forum = $forum1->id;
335 for ($i = 0; $i < 5; $i++) {
336 $this->getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
337 }
338
339 // Add 5 discussions to forum 2.
340 $record->forum = $forum2->id;
341 for ($i = 0; $i < 5; $i++) {
342 $this->getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
343 }
344
345 // Ensure that the creation times mean that the messages will be sent.
346 $this->helper_force_digest_mail_times();
347
348 // Set the tested user's default maildigest setting.
349 $DB->set_field('user', 'maildigest', 0, array('id' => $user->id));
350
351 // Set the maildigest preference for forum1 to default.
352 forum_set_user_maildigest($forum1, -1, $user);
353
354 // Set the maildigest preference for forum2 to default.
355 forum_set_user_maildigest($forum2, -1, $user);
356
357 // No digests mails should be sent, but 10 forum mails will be sent.
358 $this->helper_run_cron_check_count(0, 10, 0);
359 }
360
361 /**
362 * Sends several notifications to one user as:
363 * * daily digests coming from the user profile setting.
364 */
365 public function test_cron_profile_digest_email() {
366 global $DB, $CFG;
367
368 $this->resetAfterTest(true);
369
370 // Set up a basic user enrolled in a course.
371 $userhelper = $this->helper_setup_user_in_course();
372 $user = $userhelper->user;
373 $course1 = $userhelper->courses->course1;
374 $forum1 = $userhelper->forums->forum1;
375 $forum2 = $userhelper->forums->forum2;
376
377 // Add a discussion to the forums.
378 $record = new stdClass();
379 $record->course = $course1->id;
380 $record->userid = $user->id;
381 $record->mailnow = 1;
382
383 // Add 5 discussions to forum 1.
384 $record->forum = $forum1->id;
385 for ($i = 0; $i < 5; $i++) {
386 $this->getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
387 }
388
389 // Add 5 discussions to forum 2.
390 $record->forum = $forum2->id;
391 for ($i = 0; $i < 5; $i++) {
392 $this->getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
393 }
394
395 // Ensure that the creation times mean that the messages will be sent.
396 $this->helper_force_digest_mail_times();
397
398 // Set the tested user's default maildigest setting.
399 $DB->set_field('user', 'maildigest', 1, array('id' => $user->id));
400
401 // Set the maildigest preference for forum1 to default.
402 forum_set_user_maildigest($forum1, -1, $user);
403
404 // Set the maildigest preference for forum2 to default.
405 forum_set_user_maildigest($forum2, -1, $user);
406
407 // One digest mail should be sent, with no notifications, and one e-mail.
408 $this->helper_run_cron_check_count(1, 0, 1);
409 }
410
411 /**
412 * Sends several notifications to one user as:
413 * * daily digests coming from the per-forum setting; and
414 * * single e-mails from the profile setting.
415 */
416 public function test_cron_mixed_email_1() {
417 global $DB, $CFG;
418
419 $this->resetAfterTest(true);
420
421 // Set up a basic user enrolled in a course.
422 $userhelper = $this->helper_setup_user_in_course();
423 $user = $userhelper->user;
424 $course1 = $userhelper->courses->course1;
425 $forum1 = $userhelper->forums->forum1;
426 $forum2 = $userhelper->forums->forum2;
427
428 // Add a discussion to the forums.
429 $record = new stdClass();
430 $record->course = $course1->id;
431 $record->userid = $user->id;
432 $record->mailnow = 1;
433
434 // Add 5 discussions to forum 1.
435 $record->forum = $forum1->id;
436 for ($i = 0; $i < 5; $i++) {
437 $this->getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
438 }
439
440 // Add 5 discussions to forum 2.
441 $record->forum = $forum2->id;
442 for ($i = 0; $i < 5; $i++) {
443 $this->getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
444 }
445
446 // Ensure that the creation times mean that the messages will be sent.
447 $this->helper_force_digest_mail_times();
448
449 // Set the tested user's default maildigest setting.
450 $DB->set_field('user', 'maildigest', 0, array('id' => $user->id));
451
452 // Set the maildigest preference for forum1 to digest.
453 forum_set_user_maildigest($forum1, 1, $user);
454
455 // Set the maildigest preference for forum2 to default (single).
456 forum_set_user_maildigest($forum2, -1, $user);
457
458 // One digest e-mail should be sent, and five individual notifications.
459 $this->helper_run_cron_check_count(1, 5, 1);
460 }
461
462 /**
463 * Sends several notifications to one user as:
464 * * single e-mails from the per-forum setting; and
465 * * daily digests coming from the per-user setting.
466 */
467 public function test_cron_mixed_email_2() {
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
479 // Add a discussion to the forums.
480 $record = new stdClass();
481 $record->course = $course1->id;
482 $record->userid = $user->id;
483 $record->mailnow = 1;
484
485 // Add 5 discussions to forum 1.
486 $record->forum = $forum1->id;
487 for ($i = 0; $i < 5; $i++) {
488 $this->getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
489 }
490
491 // Add 5 discussions to forum 2.
492 $record->forum = $forum2->id;
493 for ($i = 0; $i < 5; $i++) {
494 $this->getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
495 }
496
497 // Ensure that the creation times mean that the messages will be sent.
498 $this->helper_force_digest_mail_times();
499
500 // Set the tested user's default maildigest setting.
501 $DB->set_field('user', 'maildigest', 1, array('id' => $user->id));
502
503 // Set the maildigest preference for forum1 to digest.
504 forum_set_user_maildigest($forum1, -1, $user);
505
506 // Set the maildigest preference for forum2 to single.
507 forum_set_user_maildigest($forum2, 0, $user);
508
509 // One digest e-mail should be sent, and five individual notifications.
510 $this->helper_run_cron_check_count(1, 5, 1);
511 }
512
513 /**
514 * Sends several notifications to one user as:
515 * * daily digests coming from the per-forum setting.
516 */
517 public function test_cron_forum_digest_email() {
518 global $DB, $CFG;
519
520 $this->resetAfterTest(true);
521
522 // Set up a basic user enrolled in a course.
523 $userhelper = $this->helper_setup_user_in_course();
524 $user = $userhelper->user;
525 $course1 = $userhelper->courses->course1;
526 $forum1 = $userhelper->forums->forum1;
527 $forum2 = $userhelper->forums->forum2;
528
529 // Add a discussion to the forums.
530 $record = new stdClass();
531 $record->course = $course1->id;
532 $record->userid = $user->id;
533 $record->mailnow = 1;
534
535 // Add 5 discussions to forum 1.
536 $record->forum = $forum1->id;
537 for ($i = 0; $i < 5; $i++) {
538 $this->getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
539 }
540
541 // Add 5 discussions to forum 2.
542 $record->forum = $forum2->id;
543 for ($i = 0; $i < 5; $i++) {
544 $this->getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
545 }
546
547 // Ensure that the creation times mean that the messages will be sent.
548 $this->helper_force_digest_mail_times();
549
550 // Set the tested user's default maildigest setting.
551 $DB->set_field('user', 'maildigest', 0, array('id' => $user->id));
552
553 // Set the maildigest preference for forum1 to digest (complete).
554 forum_set_user_maildigest($forum1, 1, $user);
555
556 // Set the maildigest preference for forum2 to digest (short).
557 forum_set_user_maildigest($forum2, 2, $user);
558
559 // One digest e-mail should be sent, and no individual notifications.
560 $this->helper_run_cron_check_count(1, 0, 1);
561 }
562
0462b6a1 563}