MDL-58650 core_message: always use 'popup' processor for messages
[moodle.git] / lib / tests / messagelib_test.php
CommitLineData
2cf5ab10
TH
1<?php
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16
17/**
18 * Tests for messagelib.php.
19 *
20 * @package core_message
2988b725 21 * @category phpunit
2cf5ab10
TH
22 * @copyright 2012 The Open Universtiy
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 */
25
26defined('MOODLE_INTERNAL') || die();
27
2988b725 28class core_messagelib_testcase extends advanced_testcase {
2cf5ab10 29
fd0f7ac5
RT
30 public function test_message_provider_disabled() {
31 $this->resetAfterTest();
32 $this->preventResetByRollback();
fd0f7ac5
RT
33
34 // Disable instantmessage provider.
35 $disableprovidersetting = 'moodle_instantmessage_disable';
36 set_config($disableprovidersetting, 1, 'message');
37 $preferences = get_message_output_default_preferences();
38 $this->assertTrue($preferences->$disableprovidersetting == 1);
39
cc350fd9
AD
40 $message = new \core\message\message();
41 $message->courseid = 1;
fd0f7ac5
RT
42 $message->component = 'moodle';
43 $message->name = 'instantmessage';
44 $message->userfrom = get_admin();
45 $message->userto = $this->getDataGenerator()->create_user();;
46 $message->subject = 'message subject 1';
47 $message->fullmessage = 'message body';
48 $message->fullmessageformat = FORMAT_MARKDOWN;
49 $message->fullmessagehtml = '<p>message body</p>';
50 $message->smallmessage = 'small message';
5e12b369 51 $message->notification = 0;
fd0f7ac5
RT
52
53 // Check message is not sent.
54 $sink = $this->redirectEmails();
fd0f7ac5
RT
55 message_send($message);
56 $emails = $sink->get_messages();
57 $this->assertEmpty($emails);
58
59 // Check message is sent.
60 set_config($disableprovidersetting, 0, 'message');
61 $preferences = get_message_output_default_preferences();
62 $this->assertTrue($preferences->$disableprovidersetting == 0);
63
64 $sink = $this->redirectEmails();
fd0f7ac5
RT
65 message_send($message);
66 $emails = $sink->get_messages();
67 $email = reset($emails);
68 $this->assertEquals($email->subject, 'message subject 1');
69 }
2cf5ab10
TH
70 public function test_message_get_providers_for_user() {
71 global $CFG, $DB;
72
2988b725 73 $this->resetAfterTest();
2cf5ab10
TH
74
75 $generator = $this->getDataGenerator();
76
2988b725 77 // Create a course category and course.
2cf5ab10
TH
78 $cat = $generator->create_category(array('parent' => 0));
79 $course = $generator->create_course(array('category' => $cat->id));
80 $quiz = $generator->create_module('quiz', array('course' => $course->id));
81 $user = $generator->create_user();
82
83 $coursecontext = context_course::instance($course->id);
84 $quizcontext = context_module::instance($quiz->cmid);
85 $frontpagecontext = context_course::instance(SITEID);
86
87 $studentrole = $DB->get_record('role', array('shortname' => 'student'));
88
89 // The user is a student in a course, and has the capability for quiz
90 // confirmation emails in one quiz in that course.
91 role_assign($studentrole->id, $user->id, $coursecontext->id);
92 assign_capability('mod/quiz:emailconfirmsubmission', CAP_ALLOW, $studentrole->id, $quizcontext->id);
93
94 // Give this message type to the front page role.
95 assign_capability('mod/quiz:emailwarnoverdue', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpagecontext->id);
96
97 $providers = message_get_providers_for_user($user->id);
98 $this->assertTrue($this->message_type_present('mod_forum', 'posts', $providers));
99 $this->assertTrue($this->message_type_present('mod_quiz', 'confirmation', $providers));
100 $this->assertTrue($this->message_type_present('mod_quiz', 'attempt_overdue', $providers));
101 $this->assertFalse($this->message_type_present('mod_quiz', 'submission', $providers));
102
103 // A user is a student in a different course, they should not get confirmation.
104 $course2 = $generator->create_course(array('category' => $cat->id));
105 $user2 = $generator->create_user();
106 $coursecontext2 = context_course::instance($course2->id);
107 role_assign($studentrole->id, $user2->id, $coursecontext2->id);
108 accesslib_clear_all_caches_for_unit_testing();
109 $providers = message_get_providers_for_user($user2->id);
110 $this->assertTrue($this->message_type_present('mod_forum', 'posts', $providers));
111 $this->assertFalse($this->message_type_present('mod_quiz', 'confirmation', $providers));
112
113 // Now remove the frontpage role id, and attempt_overdue message should go away.
114 unset_config('defaultfrontpageroleid');
115 accesslib_clear_all_caches_for_unit_testing();
116
117 $providers = message_get_providers_for_user($user->id);
118 $this->assertTrue($this->message_type_present('mod_quiz', 'confirmation', $providers));
119 $this->assertFalse($this->message_type_present('mod_quiz', 'attempt_overdue', $providers));
120 $this->assertFalse($this->message_type_present('mod_quiz', 'submission', $providers));
121 }
122
6ba8a4be
AD
123 public function test_message_get_providers_for_user_more() {
124 global $DB;
125
2988b725 126 $this->resetAfterTest();
6ba8a4be 127
2988b725 128 // Create a course.
6ba8a4be
AD
129 $course = $this->getDataGenerator()->create_course();
130 $coursecontext = context_course::instance($course->id);
131
132 // It would probably be better to use a quiz instance as it has capability controlled messages
2988b725
PS
133 // however mod_quiz doesn't have a data generator.
134 // Instead we're going to use backup notifications and give and take away the capability at various levels.
6ba8a4be 135 $assign = $this->getDataGenerator()->create_module('assign', array('course'=>$course->id));
780cf0a7 136 $modulecontext = context_module::instance($assign->cmid);
6ba8a4be 137
2988b725 138 // Create and enrol a teacher.
6ba8a4be
AD
139 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST);
140 $teacher = $this->getDataGenerator()->create_user();
141 role_assign($teacherrole->id, $teacher->id, $coursecontext);
142 $enrolplugin = enrol_get_plugin('manual');
143 $enrolplugin->add_instance($course);
144 $enrolinstances = enrol_get_instances($course->id, false);
145 foreach ($enrolinstances as $enrolinstance) {
146 if ($enrolinstance->enrol === 'manual') {
147 break;
148 }
149 }
150 $enrolplugin->enrol_user($enrolinstance, $teacher->id);
151
2988b725 152 // Make the teacher the current user.
6ba8a4be
AD
153 $this->setUser($teacher);
154
2988b725 155 // Teacher shouldn't have the required capability so they shouldn't be able to see the backup message.
6ba8a4be
AD
156 $this->assertFalse(has_capability('moodle/site:config', $modulecontext));
157 $providers = message_get_providers_for_user($teacher->id);
158 $this->assertFalse($this->message_type_present('moodle', 'backup', $providers));
159
2988b725
PS
160 // Give the user the required capability in an activity module.
161 // They should now be able to see the backup message.
6ba8a4be
AD
162 assign_capability('moodle/site:config', CAP_ALLOW, $teacherrole->id, $modulecontext->id, true);
163 accesslib_clear_all_caches_for_unit_testing();
780cf0a7 164 $modulecontext = context_module::instance($assign->cmid);
6ba8a4be
AD
165 $this->assertTrue(has_capability('moodle/site:config', $modulecontext));
166
167 $providers = message_get_providers_for_user($teacher->id);
168 $this->assertTrue($this->message_type_present('moodle', 'backup', $providers));
169
2988b725
PS
170 // Prohibit the capability for the user at the course level.
171 // This overrules the CAP_ALLOW at the module level.
172 // They should not be able to see the backup message.
6ba8a4be
AD
173 assign_capability('moodle/site:config', CAP_PROHIBIT, $teacherrole->id, $coursecontext->id, true);
174 accesslib_clear_all_caches_for_unit_testing();
780cf0a7 175 $modulecontext = context_module::instance($assign->cmid);
6ba8a4be
AD
176 $this->assertFalse(has_capability('moodle/site:config', $modulecontext));
177
178 $providers = message_get_providers_for_user($teacher->id);
179 // Actually, handling PROHIBITs would be too expensive. We do not
180 // care if users with PROHIBITs see a few more preferences than they should.
181 // $this->assertFalse($this->message_type_present('moodle', 'backup', $providers));
182 }
183
349f98ad
PS
184 public function test_send_message_redirection() {
185 global $DB;
186
187 $this->resetAfterTest();
188
189 $user1 = $this->getDataGenerator()->create_user();
190 $user2 = $this->getDataGenerator()->create_user();
191
192 // Test basic message redirection.
cc350fd9
AD
193 $message = new \core\message\message();
194 $message->courseid = 1;
349f98ad
PS
195 $message->component = 'moodle';
196 $message->name = 'instantmessage';
197 $message->userfrom = $user1;
198 $message->userto = $user2;
199 $message->subject = 'message subject 1';
200 $message->fullmessage = 'message body';
201 $message->fullmessageformat = FORMAT_MARKDOWN;
202 $message->fullmessagehtml = '<p>message body</p>';
203 $message->smallmessage = 'small message';
204 $message->notification = '0';
205
206 $sink = $this->redirectMessages();
207 $this->setCurrentTimeStart();
208 $messageid = message_send($message);
209 $savedmessages = $sink->get_messages();
210 $this->assertCount(1, $savedmessages);
211 $savedmessage = reset($savedmessages);
212 $this->assertEquals($messageid, $savedmessage->id);
213 $this->assertEquals($user1->id, $savedmessage->useridfrom);
214 $this->assertEquals($user2->id, $savedmessage->useridto);
215 $this->assertEquals($message->fullmessage, $savedmessage->fullmessage);
216 $this->assertEquals($message->fullmessageformat, $savedmessage->fullmessageformat);
217 $this->assertEquals($message->fullmessagehtml, $savedmessage->fullmessagehtml);
218 $this->assertEquals($message->smallmessage, $savedmessage->smallmessage);
219 $this->assertEquals($message->smallmessage, $savedmessage->smallmessage);
220 $this->assertEquals($message->notification, $savedmessage->notification);
221 $this->assertNull($savedmessage->contexturl);
222 $this->assertNull($savedmessage->contexturlname);
223 $this->assertTimeCurrent($savedmessage->timecreated);
224 $record = $DB->get_record('message_read', array('id' => $savedmessage->id), '*', MUST_EXIST);
225 $this->assertEquals($record, $savedmessage);
226 $sink->clear();
227 $this->assertFalse($DB->record_exists('message', array()));
228 $DB->delete_records('message_read', array());
229
cc350fd9
AD
230 $message = new \core\message\message();
231 $message->courseid = 1;
349f98ad
PS
232 $message->component = 'moodle';
233 $message->name = 'instantmessage';
234 $message->userfrom = $user1->id;
235 $message->userto = $user2->id;
236 $message->subject = 'message subject 1';
237 $message->fullmessage = 'message body';
238 $message->fullmessageformat = FORMAT_MARKDOWN;
239 $message->fullmessagehtml = '<p>message body</p>';
240 $message->smallmessage = 'small message';
241 $message->notification = '0';
242 $message->contexturl = new moodle_url('/');
243 $message->contexturlname = 'front';
244 $sink = $this->redirectMessages();
245 $messageid = message_send($message);
246 $savedmessages = $sink->get_messages();
247 $this->assertCount(1, $savedmessages);
248 $savedmessage = reset($savedmessages);
249 $this->assertEquals($messageid, $savedmessage->id);
250 $this->assertEquals($user1->id, $savedmessage->useridfrom);
251 $this->assertEquals($user2->id, $savedmessage->useridto);
252 $this->assertEquals($message->fullmessage, $savedmessage->fullmessage);
253 $this->assertEquals($message->fullmessageformat, $savedmessage->fullmessageformat);
254 $this->assertEquals($message->fullmessagehtml, $savedmessage->fullmessagehtml);
255 $this->assertEquals($message->smallmessage, $savedmessage->smallmessage);
256 $this->assertEquals($message->smallmessage, $savedmessage->smallmessage);
257 $this->assertEquals($message->notification, $savedmessage->notification);
258 $this->assertEquals($message->contexturl->out(), $savedmessage->contexturl);
259 $this->assertEquals($message->contexturlname, $savedmessage->contexturlname);
260 $this->assertTimeCurrent($savedmessage->timecreated);
261 $record = $DB->get_record('message_read', array('id' => $savedmessage->id), '*', MUST_EXIST);
262 $this->assertEquals($record, $savedmessage);
263 $sink->clear();
264 $this->assertFalse($DB->record_exists('message', array()));
265 $DB->delete_records('message_read', array());
266
267 // Test phpunit problem detection.
268
cc350fd9
AD
269 $message = new \core\message\message();
270 $message->courseid = 1;
349f98ad
PS
271 $message->component = 'xxxxx';
272 $message->name = 'instantmessage';
273 $message->userfrom = $user1;
274 $message->userto = $user2;
275 $message->subject = 'message subject 1';
276 $message->fullmessage = 'message body';
277 $message->fullmessageformat = FORMAT_MARKDOWN;
278 $message->fullmessagehtml = '<p>message body</p>';
279 $message->smallmessage = 'small message';
280 $message->notification = '0';
281
282 $sink = $this->redirectMessages();
283 try {
284 message_send($message);
285 } catch (moodle_exception $e) {
286 $this->assertInstanceOf('coding_exception', $e);
287 }
288 $this->assertCount(0, $sink->get_messages());
289
290 $message->component = 'moodle';
291 $message->name = 'xxx';
292 $sink = $this->redirectMessages();
293 try {
294 message_send($message);
295 } catch (moodle_exception $e) {
296 $this->assertInstanceOf('coding_exception', $e);
297 }
298 $this->assertCount(0, $sink->get_messages());
299 $sink->close();
300 $this->assertFalse($DB->record_exists('message', array()));
301 $this->assertFalse($DB->record_exists('message_read', array()));
302
303 // Invalid users.
304
cc350fd9
AD
305 $message = new \core\message\message();
306 $message->courseid = 1;
349f98ad
PS
307 $message->component = 'moodle';
308 $message->name = 'instantmessage';
309 $message->userfrom = $user1;
310 $message->userto = -1;
311 $message->subject = 'message subject 1';
312 $message->fullmessage = 'message body';
313 $message->fullmessageformat = FORMAT_MARKDOWN;
314 $message->fullmessagehtml = '<p>message body</p>';
315 $message->smallmessage = 'small message';
316 $message->notification = '0';
317
318 $messageid = message_send($message);
319 $this->assertFalse($messageid);
320 $this->assertDebuggingCalled('Attempt to send msg to unknown user');
321
cc350fd9
AD
322 $message = new \core\message\message();
323 $message->courseid = 1;
349f98ad
PS
324 $message->component = 'moodle';
325 $message->name = 'instantmessage';
326 $message->userfrom = -1;
327 $message->userto = $user2;
328 $message->subject = 'message subject 1';
329 $message->fullmessage = 'message body';
330 $message->fullmessageformat = FORMAT_MARKDOWN;
331 $message->fullmessagehtml = '<p>message body</p>';
332 $message->smallmessage = 'small message';
333 $message->notification = '0';
334
335 $messageid = message_send($message);
336 $this->assertFalse($messageid);
337 $this->assertDebuggingCalled('Attempt to send msg from unknown user');
338
cc350fd9
AD
339 $message = new \core\message\message();
340 $message->courseid = 1;
349f98ad
PS
341 $message->component = 'moodle';
342 $message->name = 'instantmessage';
343 $message->userfrom = $user1;
344 $message->userto = core_user::NOREPLY_USER;
345 $message->subject = 'message subject 1';
346 $message->fullmessage = 'message body';
347 $message->fullmessageformat = FORMAT_MARKDOWN;
348 $message->fullmessagehtml = '<p>message body</p>';
349 $message->smallmessage = 'small message';
350 $message->notification = '0';
351
352 $messageid = message_send($message);
353 $this->assertFalse($messageid);
354 $this->assertDebuggingCalled('Attempt to send msg to internal (noreply) user');
355
356 // Some debugging hints for devs.
357
358 unset($user2->emailstop);
cc350fd9
AD
359 $message = new \core\message\message();
360 $message->courseid = 1;
349f98ad
PS
361 $message->component = 'moodle';
362 $message->name = 'instantmessage';
363 $message->userfrom = $user1;
364 $message->userto = $user2;
365 $message->subject = 'message subject 1';
366 $message->fullmessage = 'message body';
367 $message->fullmessageformat = FORMAT_MARKDOWN;
368 $message->fullmessagehtml = '<p>message body</p>';
369 $message->smallmessage = 'small message';
370 $message->notification = '0';
371
372 $sink = $this->redirectMessages();
373 $messageid = message_send($message);
374 $savedmessages = $sink->get_messages();
375 $this->assertCount(1, $savedmessages);
376 $savedmessage = reset($savedmessages);
377 $this->assertEquals($messageid, $savedmessage->id);
378 $this->assertEquals($user1->id, $savedmessage->useridfrom);
379 $this->assertEquals($user2->id, $savedmessage->useridto);
380 $this->assertDebuggingCalled('Necessary properties missing in userto object, fetching full record');
381 $sink->clear();
382 $user2->emailstop = '0';
383 }
384
385 public function test_send_message() {
386 global $DB, $CFG;
387 $this->preventResetByRollback();
388 $this->resetAfterTest();
389
e0789335 390 $user1 = $this->getDataGenerator()->create_user(array('maildisplay' => 1));
349f98ad 391 $user2 = $this->getDataGenerator()->create_user();
e0789335 392 set_config('allowedemaildomains', 'example.com');
349f98ad
PS
393
394 // Test basic email redirection.
395 $this->assertFileExists("$CFG->dirroot/message/output/email/version.php");
396 $this->assertFileExists("$CFG->dirroot/message/output/popup/version.php");
397
398 $DB->set_field_select('message_processors', 'enabled', 0, "name <> 'email' AND name <> 'popup'");
399 get_message_processors(true, true);
400
401 $eventsink = $this->redirectEvents();
402
685daf1a 403 // Will always use the pop-up processor.
349f98ad
PS
404 set_user_preference('message_provider_moodle_instantmessage_loggedoff', 'none', $user2);
405
cc350fd9
AD
406 $message = new \core\message\message();
407 $message->courseid = 1;
349f98ad
PS
408 $message->component = 'moodle';
409 $message->name = 'instantmessage';
410 $message->userfrom = $user1;
411 $message->userto = $user2;
412 $message->subject = 'message subject 1';
413 $message->fullmessage = 'message body';
414 $message->fullmessageformat = FORMAT_MARKDOWN;
415 $message->fullmessagehtml = '<p>message body</p>';
416 $message->smallmessage = 'small message';
417 $message->notification = '0';
418
419 $sink = $this->redirectEmails();
420 $messageid = message_send($message);
421 $emails = $sink->get_messages();
422 $this->assertCount(0, $emails);
423 $savedmessage = $DB->get_record('message', array('id' => $messageid), '*', MUST_EXIST);
424 $sink->clear();
425 $this->assertFalse($DB->record_exists('message_read', array()));
426 $DB->delete_records('message', array());
427 $events = $eventsink->get_events();
428 $this->assertCount(1, $events);
429 $this->assertInstanceOf('\core\event\message_sent', $events[0]);
430 $eventsink->clear();
431
432 $CFG->messaging = 0;
433
cc350fd9
AD
434 $message = new \core\message\message();
435 $message->courseid = 1;
349f98ad
PS
436 $message->component = 'moodle';
437 $message->name = 'instantmessage';
438 $message->userfrom = $user1;
439 $message->userto = $user2;
440 $message->subject = 'message subject 1';
441 $message->fullmessage = 'message body';
442 $message->fullmessageformat = FORMAT_MARKDOWN;
443 $message->fullmessagehtml = '<p>message body</p>';
444 $message->smallmessage = 'small message';
445 $message->notification = '0';
446
447 $messageid = message_send($message);
448 $emails = $sink->get_messages();
449 $this->assertCount(0, $emails);
450 $savedmessage = $DB->get_record('message_read', array('id' => $messageid), '*', MUST_EXIST);
451 $sink->clear();
452 $this->assertFalse($DB->record_exists('message', array()));
453 $DB->delete_records('message_read', array());
454 $events = $eventsink->get_events();
455 $this->assertCount(2, $events);
456 $this->assertInstanceOf('\core\event\message_sent', $events[0]);
457 $this->assertInstanceOf('\core\event\message_viewed', $events[1]);
458 $eventsink->clear();
459
460 $CFG->messaging = 1;
461
cc350fd9
AD
462 $message = new \core\message\message();
463 $message->courseid = 1;
349f98ad
PS
464 $message->component = 'moodle';
465 $message->name = 'instantmessage';
466 $message->userfrom = $user1;
467 $message->userto = $user2;
468 $message->subject = 'message subject 1';
469 $message->fullmessage = 'message body';
470 $message->fullmessageformat = FORMAT_MARKDOWN;
471 $message->fullmessagehtml = '<p>message body</p>';
472 $message->smallmessage = 'small message';
473 $message->notification = '1';
474
475 $messageid = message_send($message);
476 $emails = $sink->get_messages();
477 $this->assertCount(0, $emails);
478 $savedmessage = $DB->get_record('message_read', array('id' => $messageid), '*', MUST_EXIST);
479 $sink->clear();
480 $this->assertFalse($DB->record_exists('message', array()));
481 $DB->delete_records('message_read', array());
482 $events = $eventsink->get_events();
483 $this->assertCount(2, $events);
484 $this->assertInstanceOf('\core\event\message_sent', $events[0]);
485 $this->assertInstanceOf('\core\event\message_viewed', $events[1]);
486 $eventsink->clear();
487
685daf1a 488 // Will always use the pop-up processor.
349f98ad
PS
489 set_user_preference('message_provider_moodle_instantmessage_loggedoff', 'email', $user2);
490
cc350fd9
AD
491 $message = new \core\message\message();
492 $message->courseid = 1;
349f98ad
PS
493 $message->component = 'moodle';
494 $message->name = 'instantmessage';
495 $message->userfrom = $user1;
496 $message->userto = $user2;
497 $message->subject = 'message subject 1';
498 $message->fullmessage = 'message body';
499 $message->fullmessageformat = FORMAT_MARKDOWN;
500 $message->fullmessagehtml = '<p>message body</p>';
501 $message->smallmessage = 'small message';
502 $message->notification = '0';
503
504 $user2->emailstop = '1';
505
506 $sink = $this->redirectEmails();
507 $messageid = message_send($message);
508 $emails = $sink->get_messages();
509 $this->assertCount(0, $emails);
510 $savedmessage = $DB->get_record('message', array('id' => $messageid), '*', MUST_EXIST);
511 $sink->clear();
512 $this->assertFalse($DB->record_exists('message_read', array()));
513 $DB->delete_records('message', array());
514 $events = $eventsink->get_events();
515 $this->assertCount(1, $events);
516 $this->assertInstanceOf('\core\event\message_sent', $events[0]);
517 $eventsink->clear();
518 $user2->emailstop = '0';
519
685daf1a 520 // Will always use the pop-up processor.
349f98ad
PS
521 set_user_preference('message_provider_moodle_instantmessage_loggedoff', 'email', $user2);
522
cc350fd9
AD
523 $message = new \core\message\message();
524 $message->courseid = 1;
349f98ad
PS
525 $message->component = 'moodle';
526 $message->name = 'instantmessage';
527 $message->userfrom = $user1;
528 $message->userto = $user2;
529 $message->subject = 'message subject 1';
530 $message->fullmessage = 'message body';
531 $message->fullmessageformat = FORMAT_MARKDOWN;
532 $message->fullmessagehtml = '<p>message body</p>';
533 $message->smallmessage = 'small message';
534 $message->notification = '0';
535
536 $messageid = message_send($message);
537 $emails = $sink->get_messages();
538 $this->assertCount(1, $emails);
539 $email = reset($emails);
685daf1a 540 $savedmessage = $DB->get_record('message', array('id' => $messageid), '*', MUST_EXIST);
349f98ad
PS
541 $this->assertSame($user1->email, $email->from);
542 $this->assertSame($user2->email, $email->to);
543 $this->assertSame($message->subject, $email->subject);
544 $this->assertNotEmpty($email->header);
545 $this->assertNotEmpty($email->body);
546 $sink->clear();
685daf1a 547 $this->assertFalse($DB->record_exists('message_read', array()));
349f98ad
PS
548 $DB->delete_records('message_read', array());
549 $events = $eventsink->get_events();
685daf1a 550 $this->assertCount(1, $events);
349f98ad 551 $this->assertInstanceOf('\core\event\message_sent', $events[0]);
349f98ad
PS
552 $eventsink->clear();
553
554 set_user_preference('message_provider_moodle_instantmessage_loggedoff', 'email,popup', $user2);
555
cc350fd9
AD
556 $message = new \core\message\message();
557 $message->courseid = 1;
349f98ad
PS
558 $message->component = 'moodle';
559 $message->name = 'instantmessage';
560 $message->userfrom = $user1;
561 $message->userto = $user2;
562 $message->subject = 'message subject 1';
563 $message->fullmessage = 'message body';
564 $message->fullmessageformat = FORMAT_MARKDOWN;
565 $message->fullmessagehtml = '<p>message body</p>';
566 $message->smallmessage = 'small message';
567 $message->notification = '0';
568
569 $messageid = message_send($message);
570 $emails = $sink->get_messages();
571 $this->assertCount(1, $emails);
572 $email = reset($emails);
573 $savedmessage = $DB->get_record('message', array('id' => $messageid), '*', MUST_EXIST);
574 $working = $DB->get_record('message_working', array('unreadmessageid' => $messageid), '*', MUST_EXIST);
575 $this->assertSame($user1->email, $email->from);
576 $this->assertSame($user2->email, $email->to);
577 $this->assertSame($message->subject, $email->subject);
578 $this->assertNotEmpty($email->header);
579 $this->assertNotEmpty($email->body);
580 $sink->clear();
581 $this->assertFalse($DB->record_exists('message_read', array()));
582 $DB->delete_records('message', array());
583 $events = $eventsink->get_events();
584 $this->assertCount(1, $events);
585 $this->assertInstanceOf('\core\event\message_sent', $events[0]);
586 $eventsink->clear();
587
588 set_user_preference('message_provider_moodle_instantmessage_loggedoff', 'popup', $user2);
589
cc350fd9
AD
590 $message = new \core\message\message();
591 $message->courseid = 1;
349f98ad
PS
592 $message->component = 'moodle';
593 $message->name = 'instantmessage';
594 $message->userfrom = $user1;
595 $message->userto = $user2;
596 $message->subject = 'message subject 1';
597 $message->fullmessage = 'message body';
598 $message->fullmessageformat = FORMAT_MARKDOWN;
599 $message->fullmessagehtml = '<p>message body</p>';
600 $message->smallmessage = 'small message';
601 $message->notification = '0';
602
603 $messageid = message_send($message);
604 $emails = $sink->get_messages();
605 $this->assertCount(0, $emails);
606 $savedmessage = $DB->get_record('message', array('id' => $messageid), '*', MUST_EXIST);
607 $working = $DB->get_record('message_working', array('unreadmessageid' => $messageid), '*', MUST_EXIST);
608 $sink->clear();
609 $this->assertFalse($DB->record_exists('message_read', array()));
610 $DB->delete_records('message', array());
611 $events = $eventsink->get_events();
612 $this->assertCount(1, $events);
613 $this->assertInstanceOf('\core\event\message_sent', $events[0]);
614 $eventsink->clear();
615
616 $this->assertFalse($DB->is_transaction_started());
617 $transaction = $DB->start_delegated_transaction();
618 if (!$DB->is_transaction_started()) {
619 $this->markTestSkipped('Databases that do not support transactions should not be used at all!');
620 }
621 $transaction->allow_commit();
622
685daf1a 623 // Will always use the pop-up processor.
349f98ad
PS
624 set_user_preference('message_provider_moodle_instantmessage_loggedoff', 'none', $user2);
625
cc350fd9
AD
626 $message = new \core\message\message();
627 $message->courseid = 1;
349f98ad
PS
628 $message->component = 'moodle';
629 $message->name = 'instantmessage';
630 $message->userfrom = $user1;
631 $message->userto = $user2;
632 $message->subject = 'message subject 1';
633 $message->fullmessage = 'message body';
634 $message->fullmessageformat = FORMAT_MARKDOWN;
635 $message->fullmessagehtml = '<p>message body</p>';
636 $message->smallmessage = 'small message';
637 $message->notification = '0';
638
639 $transaction = $DB->start_delegated_transaction();
640 $sink = $this->redirectEmails();
641 $messageid = message_send($message);
642 $emails = $sink->get_messages();
643 $this->assertCount(0, $emails);
644 $savedmessage = $DB->get_record('message', array('id' => $messageid), '*', MUST_EXIST);
645 $sink->clear();
646 $this->assertFalse($DB->record_exists('message_read', array()));
647 $DB->delete_records('message', array());
648 $events = $eventsink->get_events();
685daf1a 649 $this->assertCount(0, $events);
349f98ad
PS
650 $eventsink->clear();
651 $transaction->allow_commit();
652 $events = $eventsink->get_events();
685daf1a
MN
653 $this->assertCount(1, $events);
654 $this->assertInstanceOf('\core\event\message_sent', $events[0]);
349f98ad 655
685daf1a 656 // Will always use the pop-up processor.
349f98ad
PS
657 set_user_preference('message_provider_moodle_instantmessage_loggedoff', 'email', $user2);
658
cc350fd9
AD
659 $message = new \core\message\message();
660 $message->courseid = 1;
349f98ad
PS
661 $message->component = 'moodle';
662 $message->name = 'instantmessage';
663 $message->userfrom = $user1;
664 $message->userto = $user2;
665 $message->subject = 'message subject 1';
666 $message->fullmessage = 'message body';
667 $message->fullmessageformat = FORMAT_MARKDOWN;
668 $message->fullmessagehtml = '<p>message body</p>';
669 $message->smallmessage = 'small message';
670 $message->notification = '0';
671
672 $transaction = $DB->start_delegated_transaction();
673 $sink = $this->redirectEmails();
674 $messageid = message_send($message);
675 $emails = $sink->get_messages();
676 $this->assertCount(0, $emails);
677 $savedmessage = $DB->get_record('message', array('id' => $messageid), '*', MUST_EXIST);
678 $sink->clear();
679 $this->assertFalse($DB->record_exists('message_read', array()));
680 $events = $eventsink->get_events();
685daf1a
MN
681 $this->assertCount(1, $events);
682 $this->assertInstanceOf('\core\event\message_sent', $events[0]);
349f98ad
PS
683 $transaction->allow_commit();
684 $events = $eventsink->get_events();
685 $this->assertCount(2, $events);
685daf1a 686 $this->assertInstanceOf('\core\event\message_sent', $events[1]);
349f98ad
PS
687 $eventsink->clear();
688
689 $transaction = $DB->start_delegated_transaction();
690 message_send($message);
691 message_send($message);
685daf1a
MN
692 $this->assertCount(3, $DB->get_records('message'));
693 $this->assertFalse($DB->record_exists('message_read', array()));
349f98ad
PS
694 $events = $eventsink->get_events();
695 $this->assertCount(0, $events);
696 $transaction->allow_commit();
697 $events = $eventsink->get_events();
685daf1a 698 $this->assertCount(2, $events);
349f98ad 699 $this->assertInstanceOf('\core\event\message_sent', $events[0]);
685daf1a 700 $this->assertInstanceOf('\core\event\message_sent', $events[1]);
349f98ad
PS
701 $eventsink->clear();
702 $DB->delete_records('message', array());
703 $DB->delete_records('message_read', array());
704
705 $transaction = $DB->start_delegated_transaction();
706 message_send($message);
707 message_send($message);
708 $this->assertCount(2, $DB->get_records('message'));
709 $this->assertCount(0, $DB->get_records('message_read'));
710 $events = $eventsink->get_events();
711 $this->assertCount(0, $events);
712 try {
713 $transaction->rollback(new Exception('ignore'));
714 } catch (Exception $e) {
715 $this->assertSame('ignore', $e->getMessage());
716 }
717 $events = $eventsink->get_events();
718 $this->assertCount(0, $events);
719 $this->assertCount(0, $DB->get_records('message'));
720 $this->assertCount(0, $DB->get_records('message_read'));
721 message_send($message);
685daf1a
MN
722 $this->assertCount(1, $DB->get_records('message'));
723 $this->assertCount(0, $DB->get_records('message_read'));
349f98ad 724 $events = $eventsink->get_events();
685daf1a
MN
725 $this->assertCount(1, $events);
726 $this->assertInstanceOf('\core\event\message_sent', $events[0]);
349f98ad
PS
727 $sink->clear();
728 $DB->delete_records('message_read', array());
729 }
730
5cf50f96
PS
731 public function test_rollback() {
732 global $DB;
733
734 $this->resetAfterTest();
735 $this->preventResetByRollback();
5cf50f96
PS
736
737 $user1 = $this->getDataGenerator()->create_user();
738 $user2 = $this->getDataGenerator()->create_user();
739
cc350fd9
AD
740 $message = new \core\message\message();
741 $message->courseid = 1;
5cf50f96
PS
742 $message->component = 'moodle';
743 $message->name = 'instantmessage';
744 $message->userfrom = $user1;
745 $message->userto = $user2;
746 $message->subject = 'message subject 1';
747 $message->fullmessage = 'message body';
748 $message->fullmessageformat = FORMAT_MARKDOWN;
749 $message->fullmessagehtml = '<p>message body</p>';
750 $message->smallmessage = 'small message';
751 $message->notification = '0';
752
fc05c1b8
AN
753 $mailsink = $this->redirectEmails();
754
755 // Sending outside of a transaction is fine.
5cf50f96 756 message_send($message);
fc05c1b8 757 $this->assertEquals(1, $mailsink->count());
5cf50f96
PS
758
759 $transaction1 = $DB->start_delegated_transaction();
760
fc05c1b8 761 $mailsink->clear();
5cf50f96 762 message_send($message);
fc05c1b8 763 $this->assertEquals(0, $mailsink->count());
5cf50f96
PS
764
765 $transaction2 = $DB->start_delegated_transaction();
766
fc05c1b8 767 $mailsink->clear();
5cf50f96 768 message_send($message);
fc05c1b8 769 $this->assertEquals(0, $mailsink->count());
5cf50f96
PS
770
771 try {
772 $transaction2->rollback(new Exception('x'));
773 $this->fail('Expecting exception');
774 } catch (Exception $e) {}
775 $this->assertDebuggingNotCalled();
fc05c1b8 776 $this->assertEquals(0, $mailsink->count());
5cf50f96
PS
777
778 $this->assertTrue($DB->is_transaction_started());
779
780 try {
781 $transaction1->rollback(new Exception('x'));
782 $this->fail('Expecting exception');
783 } catch (Exception $e) {}
784 $this->assertDebuggingNotCalled();
fc05c1b8 785 $this->assertEquals(0, $mailsink->count());
5cf50f96
PS
786
787 $this->assertFalse($DB->is_transaction_started());
788
789 message_send($message);
fc05c1b8 790 $this->assertEquals(1, $mailsink->count());
5cf50f96
PS
791 }
792
793 public function test_forced_rollback() {
794 global $DB;
795
796 $this->resetAfterTest();
797 $this->preventResetByRollback();
798 set_config('noemailever', 1);
799
800 $user1 = $this->getDataGenerator()->create_user();
801 $user2 = $this->getDataGenerator()->create_user();
802
cc350fd9
AD
803 $message = new \core\message\message();
804 $message->courseid = 1;
5cf50f96
PS
805 $message->component = 'moodle';
806 $message->name = 'instantmessage';
807 $message->userfrom = $user1;
808 $message->userto = $user2;
809 $message->subject = 'message subject 1';
810 $message->fullmessage = 'message body';
811 $message->fullmessageformat = FORMAT_MARKDOWN;
812 $message->fullmessagehtml = '<p>message body</p>';
813 $message->smallmessage = 'small message';
814 $message->notification = '0';
815
816 message_send($message);
817 $this->assertDebuggingCalled('Not sending email due to $CFG->noemailever config setting');
818
819 $transaction1 = $DB->start_delegated_transaction();
820
821 message_send($message);
822 $this->assertDebuggingNotCalled();
823
824 $transaction2 = $DB->start_delegated_transaction();
825
826 message_send($message);
827 $this->assertDebuggingNotCalled();
828
829 $DB->force_transaction_rollback();
830 $this->assertFalse($DB->is_transaction_started());
831 $this->assertDebuggingNotCalled();
832
833 message_send($message);
834 $this->assertDebuggingCalled('Not sending email due to $CFG->noemailever config setting');
835 }
836
56b9a02e
YB
837 public function test_message_attachment_send() {
838 global $CFG;
839 $this->preventResetByRollback();
840 $this->resetAfterTest();
841
842 // Set config setting to allow attachments.
843 $CFG->allowattachments = true;
f007e899 844 unset_config('noemailever');
56b9a02e
YB
845
846 $user = $this->getDataGenerator()->create_user();
847 $context = context_user::instance($user->id);
848
849 // Create a test file.
850 $fs = get_file_storage();
851 $filerecord = array(
852 'contextid' => $context->id,
853 'component' => 'core',
854 'filearea' => 'unittest',
855 'itemid' => 99999,
856 'filepath' => '/',
857 'filename' => 'emailtest.txt'
858 );
859 $file = $fs->create_file_from_string($filerecord, 'Test content');
860
cc350fd9
AD
861 $message = new \core\message\message();
862 $message->courseid = 1;
56b9a02e
YB
863 $message->component = 'moodle';
864 $message->name = 'instantmessage';
865 $message->userfrom = get_admin();
866 $message->userto = $user;
867 $message->subject = 'message subject 1';
868 $message->fullmessage = 'message body';
869 $message->fullmessageformat = FORMAT_MARKDOWN;
870 $message->fullmessagehtml = '<p>message body</p>';
871 $message->smallmessage = 'small message';
872 $message->attachment = $file;
873 $message->attachname = 'emailtest.txt';
5e12b369 874 $message->notification = 0;
56b9a02e
YB
875
876 // Make sure we are redirecting emails.
877 $sink = $this->redirectEmails();
56b9a02e
YB
878 message_send($message);
879
880 // Get the email that we just sent.
881 $emails = $sink->get_messages();
882 $email = reset($emails);
883 $this->assertTrue(strpos($email->body, 'Content-Disposition: attachment;') !== false);
884 $this->assertTrue(strpos($email->body, 'emailtest.txt') !== false);
9a2c5257
SL
885
886 // Check if the stored file still exists after remove the temporary attachment.
887 $storedfileexists = $fs->file_exists($filerecord['contextid'], $filerecord['component'], $filerecord['filearea'],
888 $filerecord['itemid'], $filerecord['filepath'], $filerecord['filename']);
889 $this->assertTrue($storedfileexists);
56b9a02e
YB
890 }
891
2cf5ab10
TH
892 /**
893 * Is a particular message type in the list of message types.
2988b725 894 * @param string $component
2cf5ab10
TH
895 * @param string $name a message name.
896 * @param array $providers as returned by message_get_providers_for_user.
897 * @return bool whether the message type is present.
898 */
899 protected function message_type_present($component, $name, $providers) {
900 foreach ($providers as $provider) {
901 if ($provider->component == $component && $provider->name == $name) {
902 return true;
903 }
904 }
905 return false;
906 }
907}