2 // This file is part of Moodle - http://moodle.org/
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.
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.
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/>.
20 * Tests for messagelib.php.
24 * @copyright 2012 The Open Universtiy
25 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27 class messagelib_test
extends \advanced_testcase
{
29 public function test_message_provider_disabled() {
30 $this->resetAfterTest();
31 $this->preventResetByRollback();
33 // Disable instantmessage provider.
34 $disableprovidersetting = 'moodle_instantmessage_disable';
35 set_config($disableprovidersetting, 1, 'message');
36 $preferences = get_message_output_default_preferences();
37 $this->assertTrue($preferences->$disableprovidersetting == 1);
39 $message = new \core\message\
message();
40 $message->courseid
= 1;
41 $message->component
= 'moodle';
42 $message->name
= 'instantmessage';
43 $message->userfrom
= get_admin();
44 $message->userto
= $this->getDataGenerator()->create_user();;
45 $message->subject
= 'message subject 1';
46 $message->fullmessage
= 'message body';
47 $message->fullmessageformat
= FORMAT_MARKDOWN
;
48 $message->fullmessagehtml
= '<p>message body</p>';
49 $message->smallmessage
= 'small message';
50 $message->notification
= 0;
52 // Check message is not sent.
53 $sink = $this->redirectEmails();
54 message_send($message);
55 $emails = $sink->get_messages();
56 $this->assertEmpty($emails);
58 // Check message is sent.
59 set_config($disableprovidersetting, 0, 'message');
60 $preferences = get_message_output_default_preferences();
61 $this->assertTrue($preferences->$disableprovidersetting == 0);
63 $sink = $this->redirectEmails();
64 message_send($message);
65 $emails = $sink->get_messages();
66 $email = reset($emails);
67 $this->assertEquals(get_string('unreadnewmessage', 'message', fullname(get_admin())), $email->subject
);
69 public function test_message_get_providers_for_user() {
72 $this->resetAfterTest();
74 $generator = $this->getDataGenerator();
76 // Create a course category and course.
77 $cat = $generator->create_category(array('parent' => 0));
78 $course = $generator->create_course(array('category' => $cat->id
));
79 $quiz = $generator->create_module('quiz', array('course' => $course->id
));
80 $user = $generator->create_user();
82 $coursecontext = \context_course
::instance($course->id
);
83 $quizcontext = \context_module
::instance($quiz->cmid
);
84 $frontpagecontext = \context_course
::instance(SITEID
);
86 $studentrole = $DB->get_record('role', array('shortname' => 'student'));
88 // The user is a student in a course, and has the capability for quiz
89 // confirmation emails in one quiz in that course.
90 role_assign($studentrole->id
, $user->id
, $coursecontext->id
);
91 assign_capability('mod/quiz:emailconfirmsubmission', CAP_ALLOW
, $studentrole->id
, $quizcontext->id
);
93 // Give this message type to the front page role.
94 assign_capability('mod/quiz:emailwarnoverdue', CAP_ALLOW
, $CFG->defaultfrontpageroleid
, $frontpagecontext->id
);
96 $providers = message_get_providers_for_user($user->id
);
97 $this->assertTrue($this->message_type_present('mod_forum', 'posts', $providers));
98 $this->assertTrue($this->message_type_present('mod_quiz', 'confirmation', $providers));
99 $this->assertTrue($this->message_type_present('mod_quiz', 'attempt_overdue', $providers));
100 $this->assertFalse($this->message_type_present('mod_quiz', 'submission', $providers));
102 // A user is a student in a different course, they should not get confirmation.
103 $course2 = $generator->create_course(array('category' => $cat->id
));
104 $user2 = $generator->create_user();
105 $coursecontext2 = \context_course
::instance($course2->id
);
106 role_assign($studentrole->id
, $user2->id
, $coursecontext2->id
);
107 accesslib_clear_all_caches_for_unit_testing();
108 $providers = message_get_providers_for_user($user2->id
);
109 $this->assertTrue($this->message_type_present('mod_forum', 'posts', $providers));
110 $this->assertFalse($this->message_type_present('mod_quiz', 'confirmation', $providers));
112 // Now remove the frontpage role id, and attempt_overdue message should go away.
113 unset_config('defaultfrontpageroleid');
114 accesslib_clear_all_caches_for_unit_testing();
116 $providers = message_get_providers_for_user($user->id
);
117 $this->assertTrue($this->message_type_present('mod_quiz', 'confirmation', $providers));
118 $this->assertFalse($this->message_type_present('mod_quiz', 'attempt_overdue', $providers));
119 $this->assertFalse($this->message_type_present('mod_quiz', 'submission', $providers));
122 public function test_message_get_providers_for_user_more() {
125 $this->resetAfterTest();
128 $course = $this->getDataGenerator()->create_course();
129 $coursecontext = \context_course
::instance($course->id
);
131 // It would probably be better to use a quiz instance as it has capability controlled messages
132 // however mod_quiz doesn't have a data generator.
133 // Instead we're going to use backup notifications and give and take away the capability at various levels.
134 $assign = $this->getDataGenerator()->create_module('assign', array('course'=>$course->id
));
135 $modulecontext = \context_module
::instance($assign->cmid
);
137 // Create and enrol a teacher.
138 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST
);
139 $teacher = $this->getDataGenerator()->create_user();
140 role_assign($teacherrole->id
, $teacher->id
, $coursecontext);
141 $enrolplugin = enrol_get_plugin('manual');
142 $enrolplugin->add_instance($course);
143 $enrolinstances = enrol_get_instances($course->id
, false);
144 foreach ($enrolinstances as $enrolinstance) {
145 if ($enrolinstance->enrol
=== 'manual') {
149 $enrolplugin->enrol_user($enrolinstance, $teacher->id
);
151 // Make the teacher the current user.
152 $this->setUser($teacher);
154 // Teacher shouldn't have the required capability so they shouldn't be able to see the backup message.
155 $this->assertFalse(has_capability('moodle/site:config', $modulecontext));
156 $providers = message_get_providers_for_user($teacher->id
);
157 $this->assertFalse($this->message_type_present('moodle', 'backup', $providers));
159 // Give the user the required capability in an activity module.
160 // They should now be able to see the backup message.
161 assign_capability('moodle/site:config', CAP_ALLOW
, $teacherrole->id
, $modulecontext->id
, true);
162 accesslib_clear_all_caches_for_unit_testing();
163 $modulecontext = \context_module
::instance($assign->cmid
);
164 $this->assertTrue(has_capability('moodle/site:config', $modulecontext));
166 $providers = message_get_providers_for_user($teacher->id
);
167 $this->assertTrue($this->message_type_present('moodle', 'backup', $providers));
169 // Prohibit the capability for the user at the course level.
170 // This overrules the CAP_ALLOW at the module level.
171 // They should not be able to see the backup message.
172 assign_capability('moodle/site:config', CAP_PROHIBIT
, $teacherrole->id
, $coursecontext->id
, true);
173 accesslib_clear_all_caches_for_unit_testing();
174 $modulecontext = \context_module
::instance($assign->cmid
);
175 $this->assertFalse(has_capability('moodle/site:config', $modulecontext));
177 $providers = message_get_providers_for_user($teacher->id
);
178 // Actually, handling PROHIBITs would be too expensive. We do not
179 // care if users with PROHIBITs see a few more preferences than they should.
180 // $this->assertFalse($this->message_type_present('moodle', 'backup', $providers));
183 public function test_send_message_redirection() {
186 $this->resetAfterTest();
188 $user1 = $this->getDataGenerator()->create_user();
189 $user2 = $this->getDataGenerator()->create_user();
191 // Test basic message redirection.
192 $message = new \core\message\
message();
193 $message->courseid
= 1;
194 $message->component
= 'moodle';
195 $message->name
= 'instantmessage';
196 $message->userfrom
= $user1;
197 $message->userto
= $user2;
198 $message->subject
= 'message subject 1';
199 $message->fullmessage
= 'message body';
200 $message->fullmessageformat
= FORMAT_MARKDOWN
;
201 $message->fullmessagehtml
= '<p>message body</p>';
202 $message->smallmessage
= 'small message';
203 $message->notification
= '0';
204 $message->customdata
= ['datakey' => 'data'];
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->assertEquals($message->customdata
, $savedmessage->customdata
);
222 $this->assertStringContainsString('datakey', $savedmessage->customdata
);
223 // Check it was a unserialisable json.
224 $customdata = json_decode($savedmessage->customdata
);
225 $this->assertEquals('data', $customdata->datakey
);
226 $this->assertEquals(1, $customdata->courseid
);
227 $this->assertTimeCurrent($savedmessage->timecreated
);
228 $record = $DB->get_record('messages', array('id' => $savedmessage->id
), '*', MUST_EXIST
);
229 unset($savedmessage->useridto
);
230 unset($savedmessage->notification
);
231 $this->assertEquals($record, $savedmessage);
233 $this->assertTrue($DB->record_exists('message_user_actions', array('userid' => $user2->id
, 'messageid' => $messageid,
234 'action' => \core_message\api
::MESSAGE_ACTION_READ
)));
235 $DB->delete_records('messages', array());
237 $message = new \core\message\
message();
238 $message->courseid
= 1;
239 $message->component
= 'moodle';
240 $message->name
= 'instantmessage';
241 $message->userfrom
= $user1->id
;
242 $message->userto
= $user2->id
;
243 $message->subject
= 'message subject 1';
244 $message->fullmessage
= 'message body';
245 $message->fullmessageformat
= FORMAT_MARKDOWN
;
246 $message->fullmessagehtml
= '<p>message body</p>';
247 $message->smallmessage
= 'small message';
248 $message->notification
= '0';
250 $sink = $this->redirectMessages();
251 $messageid = message_send($message);
252 $savedmessages = $sink->get_messages();
253 $this->assertCount(1, $savedmessages);
254 $savedmessage = reset($savedmessages);
255 $this->assertEquals($messageid, $savedmessage->id
);
256 $this->assertEquals($user1->id
, $savedmessage->useridfrom
);
257 $this->assertEquals($user2->id
, $savedmessage->useridto
);
258 $this->assertEquals($message->fullmessage
, $savedmessage->fullmessage
);
259 $this->assertEquals($message->fullmessageformat
, $savedmessage->fullmessageformat
);
260 $this->assertEquals($message->fullmessagehtml
, $savedmessage->fullmessagehtml
);
261 $this->assertEquals($message->smallmessage
, $savedmessage->smallmessage
);
262 $this->assertEquals($message->smallmessage
, $savedmessage->smallmessage
);
263 $this->assertEquals($message->notification
, $savedmessage->notification
);
264 $this->assertTimeCurrent($savedmessage->timecreated
);
265 $record = $DB->get_record('messages', array('id' => $savedmessage->id
), '*', MUST_EXIST
);
266 unset($savedmessage->useridto
);
267 unset($savedmessage->notification
);
268 $this->assertEquals($record, $savedmessage);
270 $this->assertTrue($DB->record_exists('message_user_actions', array('userid' => $user2->id
, 'messageid' => $messageid,
271 'action' => \core_message\api
::MESSAGE_ACTION_READ
)));
272 $DB->delete_records('messages', array());
274 // Test phpunit problem detection.
276 $message = new \core\message\
message();
277 $message->courseid
= 1;
278 $message->component
= 'xxxxx';
279 $message->name
= 'instantmessage';
280 $message->userfrom
= $user1;
281 $message->userto
= $user2;
282 $message->subject
= 'message subject 1';
283 $message->fullmessage
= 'message body';
284 $message->fullmessageformat
= FORMAT_MARKDOWN
;
285 $message->fullmessagehtml
= '<p>message body</p>';
286 $message->smallmessage
= 'small message';
287 $message->notification
= '0';
289 $sink = $this->redirectMessages();
291 message_send($message);
292 } catch (\moodle_exception
$e) {
293 $this->assertInstanceOf('coding_exception', $e);
295 $this->assertCount(0, $sink->get_messages());
296 $this->assertDebuggingCalled('Attempt to send msg from a provider xxxxx/instantmessage '.
297 'that is inactive or not allowed for the user id='.$user2->id
);
299 $message->component
= 'moodle';
300 $message->name
= 'xxx';
301 $sink = $this->redirectMessages();
303 message_send($message);
304 } catch (\moodle_exception
$e) {
305 $this->assertInstanceOf('coding_exception', $e);
307 $this->assertCount(0, $sink->get_messages());
308 $this->assertDebuggingCalled('Attempt to send msg from a provider moodle/xxx '.
309 'that is inactive or not allowed for the user id='.$user2->id
);
311 $this->assertFalse($DB->record_exists('messages', array()));
315 $message = new \core\message\
message();
316 $message->courseid
= 1;
317 $message->component
= 'moodle';
318 $message->name
= 'instantmessage';
319 $message->userfrom
= $user1;
320 $message->userto
= -1;
321 $message->subject
= 'message subject 1';
322 $message->fullmessage
= 'message body';
323 $message->fullmessageformat
= FORMAT_MARKDOWN
;
324 $message->fullmessagehtml
= '<p>message body</p>';
325 $message->smallmessage
= 'small message';
326 $message->notification
= '0';
328 $messageid = message_send($message);
329 $this->assertFalse($messageid);
330 $this->assertDebuggingCalled('Attempt to send msg to unknown user');
332 $message = new \core\message\
message();
333 $message->courseid
= 1;
334 $message->component
= 'moodle';
335 $message->name
= 'instantmessage';
336 $message->userfrom
= -1;
337 $message->userto
= $user2;
338 $message->subject
= 'message subject 1';
339 $message->fullmessage
= 'message body';
340 $message->fullmessageformat
= FORMAT_MARKDOWN
;
341 $message->fullmessagehtml
= '<p>message body</p>';
342 $message->smallmessage
= 'small message';
343 $message->notification
= '0';
345 $messageid = message_send($message);
346 $this->assertFalse($messageid);
347 $this->assertDebuggingCalled('Attempt to send msg from unknown user');
349 $message = new \core\message\
message();
350 $message->courseid
= 1;
351 $message->component
= 'moodle';
352 $message->name
= 'instantmessage';
353 $message->userfrom
= $user1;
354 $message->userto
= \core_user
::NOREPLY_USER
;
355 $message->subject
= 'message subject 1';
356 $message->fullmessage
= 'message body';
357 $message->fullmessageformat
= FORMAT_MARKDOWN
;
358 $message->fullmessagehtml
= '<p>message body</p>';
359 $message->smallmessage
= 'small message';
360 $message->notification
= '0';
362 $messageid = message_send($message);
363 $this->assertFalse($messageid);
364 $this->assertDebuggingCalled('Attempt to send msg to internal (noreply) user');
366 // Some debugging hints for devs.
368 unset($user2->emailstop
);
369 $message = new \core\message\
message();
370 $message->courseid
= 1;
371 $message->component
= 'moodle';
372 $message->name
= 'instantmessage';
373 $message->userfrom
= $user1;
374 $message->userto
= $user2;
375 $message->subject
= 'message subject 1';
376 $message->fullmessage
= 'message body';
377 $message->fullmessageformat
= FORMAT_MARKDOWN
;
378 $message->fullmessagehtml
= '<p>message body</p>';
379 $message->smallmessage
= 'small message';
380 $message->notification
= '0';
382 $sink = $this->redirectMessages();
383 $messageid = message_send($message);
384 $savedmessages = $sink->get_messages();
385 $this->assertCount(1, $savedmessages);
386 $savedmessage = reset($savedmessages);
387 $this->assertEquals($messageid, $savedmessage->id
);
388 $this->assertEquals($user1->id
, $savedmessage->useridfrom
);
389 $this->assertEquals($user2->id
, $savedmessage->useridto
);
390 $this->assertDebuggingCalled('Necessary properties missing in userto object, fetching full record');
392 $user2->emailstop
= '0';
395 public function test_send_message() {
397 $this->preventResetByRollback();
398 $this->resetAfterTest();
400 $user1 = $this->getDataGenerator()->create_user(array('maildisplay' => 1));
401 $user2 = $this->getDataGenerator()->create_user();
402 set_config('allowedemaildomains', 'example.com');
404 // Test basic email redirection.
405 $this->assertFileExists("$CFG->dirroot/message/output/email/version.php");
406 $this->assertFileExists("$CFG->dirroot/message/output/popup/version.php");
408 $DB->set_field_select('message_processors', 'enabled', 0, "name <> 'email' AND name <> 'popup'");
409 get_message_processors(true, true);
411 $eventsink = $this->redirectEvents();
413 // Will always use the pop-up processor.
414 set_user_preference('message_provider_moodle_instantmessage_loggedoff', 'none', $user2);
416 $message = new \core\message\
message();
417 $message->courseid
= 1;
418 $message->component
= 'moodle';
419 $message->name
= 'instantmessage';
420 $message->userfrom
= $user1;
421 $message->userto
= $user2;
422 $message->subject
= 'message subject 1';
423 $message->fullmessage
= 'message body';
424 $message->fullmessageformat
= FORMAT_MARKDOWN
;
425 $message->fullmessagehtml
= '<p>message body</p>';
426 $message->smallmessage
= 'small message';
427 $message->notification
= '0';
429 $sink = $this->redirectEmails();
430 $messageid = message_send($message);
431 $emails = $sink->get_messages();
432 $this->assertCount(0, $emails);
433 $savedmessage = $DB->get_record('messages', array('id' => $messageid), '*', MUST_EXIST
);
435 $this->assertFalse($DB->record_exists('message_user_actions', array()));
436 $DB->delete_records('messages', array());
437 $DB->delete_records('message_user_actions', array());
438 $events = $eventsink->get_events();
439 $this->assertCount(1, $events);
440 $this->assertInstanceOf('\core\event\message_sent', $events[0]);
443 // No messages are sent when the feature is disabled.
446 $message = new \core\message\
message();
447 $message->courseid
= 1;
448 $message->component
= 'moodle';
449 $message->name
= 'instantmessage';
450 $message->userfrom
= $user1;
451 $message->userto
= $user2;
452 $message->subject
= 'message subject 1';
453 $message->fullmessage
= 'message body';
454 $message->fullmessageformat
= FORMAT_MARKDOWN
;
455 $message->fullmessagehtml
= '<p>message body</p>';
456 $message->smallmessage
= 'small message';
457 $message->notification
= '0';
459 $messageid = message_send($message);
460 $this->assertFalse($messageid);
461 $this->assertDebuggingCalled('Attempt to send msg from a provider moodle/instantmessage '.
462 'that is inactive or not allowed for the user id='.$user2->id
);
463 $emails = $sink->get_messages();
464 $this->assertCount(0, $emails);
466 $DB->delete_records('messages', array());
467 $DB->delete_records('message_user_actions', array());
468 $events = $eventsink->get_events();
469 $this->assertCount(0, $events);
472 // Example of a message that is sent and viewed.
475 $message = new \core\message\
message();
476 $message->courseid
= 1;
477 $message->component
= 'moodle';
478 $message->name
= 'instantmessage';
479 $message->userfrom
= $user1;
480 $message->userto
= $user2;
481 $message->subject
= 'message subject 1';
482 $message->fullmessage
= 'message body';
483 $message->fullmessageformat
= FORMAT_MARKDOWN
;
484 $message->fullmessagehtml
= '<p>message body</p>';
485 $message->smallmessage
= 'small message';
486 $message->notification
= '1';
488 $messageid = message_send($message);
489 $emails = $sink->get_messages();
490 $this->assertCount(0, $emails);
491 $savedmessage = $DB->get_record('notifications', array('id' => $messageid), '*', MUST_EXIST
);
493 $this->assertFalse($DB->record_exists('messages', array()));
494 $DB->delete_records('notifications', array());
495 $events = $eventsink->get_events();
496 $this->assertCount(2, $events);
497 $this->assertInstanceOf('\core\event\notification_sent', $events[0]);
498 $this->assertInstanceOf('\core\event\notification_viewed', $events[1]);
501 // Will always use the pop-up processor.
502 set_user_preference('message_provider_moodle_instantmessage_loggedoff', 'email', $user2);
504 $message = new \core\message\
message();
505 $message->courseid
= 1;
506 $message->component
= 'moodle';
507 $message->name
= 'instantmessage';
508 $message->userfrom
= $user1;
509 $message->userto
= $user2;
510 $message->subject
= 'message subject 1';
511 $message->fullmessage
= 'message body';
512 $message->fullmessageformat
= FORMAT_MARKDOWN
;
513 $message->fullmessagehtml
= '<p>message body</p>';
514 $message->smallmessage
= 'small message';
515 $message->notification
= '0';
517 $user2->emailstop
= '1';
519 $sink = $this->redirectEmails();
520 $messageid = message_send($message);
521 $emails = $sink->get_messages();
522 $this->assertCount(0, $emails);
523 $savedmessage = $DB->get_record('messages', array('id' => $messageid), '*', MUST_EXIST
);
525 $this->assertFalse($DB->record_exists('message_user_actions', array()));
526 $DB->delete_records('messages', array());
527 $DB->delete_records('message_user_actions', array());
528 $events = $eventsink->get_events();
529 $this->assertCount(1, $events);
530 $this->assertInstanceOf('\core\event\message_sent', $events[0]);
532 $user2->emailstop
= '0';
534 // Will always use the pop-up processor.
535 set_user_preference('message_provider_moodle_instantmessage_loggedoff', 'email', $user2);
537 $message = new \core\message\
message();
538 $message->courseid
= 1;
539 $message->component
= 'moodle';
540 $message->name
= 'instantmessage';
541 $message->userfrom
= $user1;
542 $message->userto
= $user2;
543 $message->subject
= 'message subject 1';
544 $message->fullmessage
= 'message body';
545 $message->fullmessageformat
= FORMAT_MARKDOWN
;
546 $message->fullmessagehtml
= '<p>message body</p>';
547 $message->smallmessage
= 'small message';
548 $message->notification
= '0';
550 $messageid = message_send($message);
551 $emails = $sink->get_messages();
552 $this->assertCount(1, $emails);
553 $email = reset($emails);
554 $savedmessage = $DB->get_record('messages', array('id' => $messageid), '*', MUST_EXIST
);
555 $this->assertSame($user1->email
, $email->from
);
556 $this->assertSame($user2->email
, $email->to
);
557 $this->assertSame(get_string('unreadnewmessage', 'message', fullname($user1)), $email->subject
);
558 $this->assertNotEmpty($email->header
);
559 $this->assertNotEmpty($email->body
);
561 $this->assertFalse($DB->record_exists('message_user_actions', array()));
562 $DB->delete_records('message_user_actions', array());
563 $events = $eventsink->get_events();
564 $this->assertCount(1, $events);
565 $this->assertInstanceOf('\core\event\message_sent', $events[0]);
568 set_user_preference('message_provider_moodle_instantmessage_loggedoff', 'email,popup', $user2);
570 $message = new \core\message\
message();
571 $message->courseid
= 1;
572 $message->component
= 'moodle';
573 $message->name
= 'instantmessage';
574 $message->userfrom
= $user1;
575 $message->userto
= $user2;
576 $message->subject
= 'message subject 1';
577 $message->fullmessage
= 'message body';
578 $message->fullmessageformat
= FORMAT_MARKDOWN
;
579 $message->fullmessagehtml
= '<p>message body</p>';
580 $message->smallmessage
= 'small message';
581 $message->notification
= '0';
583 $messageid = message_send($message);
584 $emails = $sink->get_messages();
585 $this->assertCount(1, $emails);
586 $email = reset($emails);
587 $savedmessage = $DB->get_record('messages', array('id' => $messageid), '*', MUST_EXIST
);
588 $this->assertSame($user1->email
, $email->from
);
589 $this->assertSame($user2->email
, $email->to
);
590 $this->assertSame(get_string('unreadnewmessage', 'message', fullname($user1)), $email->subject
);
591 $this->assertNotEmpty($email->header
);
592 $this->assertNotEmpty($email->body
);
594 $this->assertFalse($DB->record_exists('message_user_actions', array()));
595 $DB->delete_records('messages', array());
596 $DB->delete_records('message_user_actions', array());
597 $events = $eventsink->get_events();
598 $this->assertCount(1, $events);
599 $this->assertInstanceOf('\core\event\message_sent', $events[0]);
602 set_user_preference('message_provider_moodle_instantmessage_loggedoff', 'popup', $user2);
604 $message = new \core\message\
message();
605 $message->courseid
= 1;
606 $message->component
= 'moodle';
607 $message->name
= 'instantmessage';
608 $message->userfrom
= $user1;
609 $message->userto
= $user2;
610 $message->subject
= 'message subject 1';
611 $message->fullmessage
= 'message body';
612 $message->fullmessageformat
= FORMAT_MARKDOWN
;
613 $message->fullmessagehtml
= '<p>message body</p>';
614 $message->smallmessage
= 'small message';
615 $message->notification
= '0';
617 $messageid = message_send($message);
618 $emails = $sink->get_messages();
619 $this->assertCount(0, $emails);
620 $savedmessage = $DB->get_record('messages', array('id' => $messageid), '*', MUST_EXIST
);
622 $this->assertFalse($DB->record_exists('message_user_actions', array()));
623 $DB->delete_records('messages', array());
624 $events = $eventsink->get_events();
625 $this->assertCount(1, $events);
626 $this->assertInstanceOf('\core\event\message_sent', $events[0]);
629 $this->assertFalse($DB->is_transaction_started());
630 $transaction = $DB->start_delegated_transaction();
631 if (!$DB->is_transaction_started()) {
632 $this->markTestSkipped('Databases that do not support transactions should not be used at all!');
634 $transaction->allow_commit();
636 // Will always use the pop-up processor.
637 set_user_preference('message_provider_moodle_instantmessage_loggedoff', 'none', $user2);
639 $message = new \core\message\
message();
640 $message->courseid
= 1;
641 $message->component
= 'moodle';
642 $message->name
= 'instantmessage';
643 $message->userfrom
= $user1;
644 $message->userto
= $user2;
645 $message->subject
= 'message subject 1';
646 $message->fullmessage
= 'message body';
647 $message->fullmessageformat
= FORMAT_MARKDOWN
;
648 $message->fullmessagehtml
= '<p>message body</p>';
649 $message->smallmessage
= 'small message';
650 $message->notification
= '0';
652 $transaction = $DB->start_delegated_transaction();
653 $sink = $this->redirectEmails();
654 $messageid = message_send($message);
655 $emails = $sink->get_messages();
656 $this->assertCount(0, $emails);
657 $savedmessage = $DB->get_record('messages', array('id' => $messageid), '*', MUST_EXIST
);
659 $this->assertFalse($DB->record_exists('message_user_actions', array()));
660 $DB->delete_records('messages', array());
661 $events = $eventsink->get_events();
662 $this->assertCount(0, $events);
664 $transaction->allow_commit();
665 $events = $eventsink->get_events();
666 $this->assertCount(1, $events);
667 $this->assertInstanceOf('\core\event\message_sent', $events[0]);
669 // Will always use the pop-up processor.
670 set_user_preference('message_provider_moodle_instantmessage_loggedoff', 'email', $user2);
672 $message = new \core\message\
message();
673 $message->courseid
= 1;
674 $message->component
= 'moodle';
675 $message->name
= 'instantmessage';
676 $message->userfrom
= $user1;
677 $message->userto
= $user2;
678 $message->subject
= 'message subject 1';
679 $message->fullmessage
= 'message body';
680 $message->fullmessageformat
= FORMAT_MARKDOWN
;
681 $message->fullmessagehtml
= '<p>message body</p>';
682 $message->smallmessage
= 'small message';
683 $message->notification
= '0';
685 $transaction = $DB->start_delegated_transaction();
686 $sink = $this->redirectEmails();
687 $messageid = message_send($message);
688 $emails = $sink->get_messages();
689 $this->assertCount(0, $emails);
690 $savedmessage = $DB->get_record('messages', array('id' => $messageid), '*', MUST_EXIST
);
692 $this->assertFalse($DB->record_exists('message_user_actions', array()));
693 $events = $eventsink->get_events();
694 $this->assertCount(1, $events);
695 $this->assertInstanceOf('\core\event\message_sent', $events[0]);
696 $transaction->allow_commit();
697 $events = $eventsink->get_events();
698 $this->assertCount(2, $events);
699 $this->assertInstanceOf('\core\event\message_sent', $events[1]);
702 $transaction = $DB->start_delegated_transaction();
703 message_send($message);
704 message_send($message);
705 $this->assertCount(3, $DB->get_records('messages'));
706 $this->assertFalse($DB->record_exists('message_user_actions', array()));
707 $events = $eventsink->get_events();
708 $this->assertCount(0, $events);
709 $transaction->allow_commit();
710 $events = $eventsink->get_events();
711 $this->assertCount(2, $events);
712 $this->assertInstanceOf('\core\event\message_sent', $events[0]);
713 $this->assertInstanceOf('\core\event\message_sent', $events[1]);
715 $DB->delete_records('messages', array());
717 $transaction = $DB->start_delegated_transaction();
718 message_send($message);
719 message_send($message);
720 $this->assertCount(2, $DB->get_records('messages'));
721 $this->assertCount(0, $DB->get_records('message_user_actions'));
722 $events = $eventsink->get_events();
723 $this->assertCount(0, $events);
725 $transaction->rollback(new \
Exception('ignore'));
726 } catch (\Exception
$e) {
727 $this->assertSame('ignore', $e->getMessage());
729 $events = $eventsink->get_events();
730 $this->assertCount(0, $events);
731 $this->assertCount(0, $DB->get_records('messages'));
732 message_send($message);
733 $this->assertCount(1, $DB->get_records('messages'));
734 $this->assertCount(0, $DB->get_records('message_user_actions'));
735 $events = $eventsink->get_events();
736 $this->assertCount(1, $events);
737 $this->assertInstanceOf('\core\event\message_sent', $events[0]);
742 * Tests calling message_send() with $eventdata representing a message to an individual conversation.
744 * This test will verify:
745 * - that the 'messages' record is created.
746 * - that the processors will be called for each conversation member, except the sender.
747 * - the a single event will be generated - 'message_sent'
749 * Note: We won't redirect/capture messages in this test because doing so causes message_send() to return early, before
750 * processors and events code is called. We need to test this code here, as we generally redirect messages elsewhere and we
751 * need to be sure this is covered.
753 public function test_message_send_to_conversation_individual() {
755 $this->preventResetByRollback();
756 $this->resetAfterTest();
758 // Create some users and a conversation between them.
759 $user1 = $this->getDataGenerator()->create_user(array('maildisplay' => 1));
760 $user2 = $this->getDataGenerator()->create_user();
761 set_config('allowedemaildomains', 'example.com');
762 $conversation = \core_message\api
::create_conversation(\core_message\api
::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL
,
763 [$user1->id
, $user2->id
], '1:1 project discussion');
765 // Generate the message.
766 $message = new \core\message\
message();
767 $message->courseid
= 1;
768 $message->component
= 'moodle';
769 $message->name
= 'instantmessage';
770 $message->userfrom
= $user1;
771 $message->convid
= $conversation->id
;
772 $message->subject
= 'message subject 1';
773 $message->fullmessage
= 'message body';
774 $message->fullmessageformat
= FORMAT_MARKDOWN
;
775 $message->fullmessagehtml
= '<p>message body</p>';
776 $message->smallmessage
= 'small message';
777 $message->notification
= '0';
779 // Content specific to the email processor.
780 $content = array('*' => array('header' => ' test ', 'footer' => ' test '));
781 $message->set_additional_content('email', $content);
783 // Ensure we're going to hit the email processor for this user.
784 $DB->set_field_select('message_processors', 'enabled', 0, "name <> 'email'");
785 set_user_preference('message_provider_moodle_instantmessage_loggedoff', 'email', $user2);
787 // Now, send a message and verify the message processors (in this case, email) are hit.
788 $sink = $this->redirectEmails();
789 $messageid = message_send($message);
790 $emails = $sink->get_messages();
791 $this->assertCount(1, $emails);
792 $email = reset($emails);
794 // Verify the record was created in 'messages'.
795 $recordexists = $DB->record_exists('messages', ['id' => $messageid]);
796 $this->assertTrue($recordexists);
798 // Verify the email information.
799 $this->assertSame($user1->email
, $email->from
);
800 $this->assertSame($user2->email
, $email->to
);
802 // The message subject is generated during the call for conversation messages,
803 // as the conversation may have many members having different lang preferences.
804 $this->assertSame(get_string('unreadnewmessage', 'message', fullname($user1)), $email->subject
);
806 // The email content will have had an emailtagline appended to it, based on lang prefs,
807 // so verify the expected beginning and ends.
808 $this->assertNotEmpty($email->header
);
809 $this->assertNotEmpty($email->body
);
810 $this->assertMatchesRegularExpression('/test.*message body.*test/s', $email->body
);
813 // Now, send the message again, and verify that the event fired includes the courseid and conversationid.
814 $eventsink = $this->redirectEvents();
815 $messageid = message_send($message);
816 $events = $eventsink->get_events();
817 $this->assertCount(1, $events);
818 $event = reset($events);
819 $this->assertInstanceOf(\core\event\message_sent
::class, $event);
820 $this->assertEquals($user1->id
, $event->userid
);
821 $this->assertEquals($user2->id
, $event->relateduserid
);
822 $this->assertEquals($message->courseid
, $event->other
['courseid']);
829 * Tests calling message_send() with $eventdata representing a message to a self-conversation.
831 * This test will verify:
832 * - that the 'messages' record is created.
833 * - that the processors is not called (for now self-conversations are not processed).
834 * - the a single event will be generated - 'message_sent'
836 * Note: We won't redirect/capture messages in this test because doing so causes message_send() to return early, before
837 * processors and events code is called. We need to test this code here, as we generally redirect messages elsewhere and we
838 * need to be sure this is covered.
840 public function test_message_send_to_self_conversation() {
842 $this->preventResetByRollback();
843 $this->resetAfterTest();
845 // Create some users and a conversation between them.
846 $user1 = $this->getDataGenerator()->create_user(array('maildisplay' => 1));
847 set_config('allowedemaildomains', 'example.com');
848 $conversation = \core_message\api
::create_conversation(\core_message\api
::MESSAGE_CONVERSATION_TYPE_SELF
,
851 // Generate the message.
852 $message = new \core\message\
message();
853 $message->courseid
= 1;
854 $message->component
= 'moodle';
855 $message->name
= 'instantmessage';
856 $message->userfrom
= $user1;
857 $message->convid
= $conversation->id
;
858 $message->subject
= 'message subject 1';
859 $message->fullmessage
= 'message body';
860 $message->fullmessageformat
= FORMAT_MARKDOWN
;
861 $message->fullmessagehtml
= '<p>message body</p>';
862 $message->smallmessage
= 'small message';
863 $message->notification
= '0';
865 // Content specific to the email processor.
866 $content = array('*' => array('header' => ' test ', 'footer' => ' test '));
867 $message->set_additional_content('email', $content);
869 // Ensure we're going to hit the email processor for this user.
870 $DB->set_field_select('message_processors', 'enabled', 0, "name <> 'email'");
871 set_user_preference('message_provider_moodle_instantmessage_loggedoff', 'email', $user1);
873 // Now, send a message and verify the message processors are empty (self-conversations are not processed for now).
874 $sink = $this->redirectEmails();
875 $messageid = message_send($message);
876 $emails = $sink->get_messages();
877 $this->assertCount(0, $emails);
882 * Tests calling message_send() with $eventdata representing a message to an group conversation.
884 * This test will verify:
885 * - that the 'messages' record is created.
886 * - that the processors will be called for each conversation member, except the sender.
887 * - the a single event will be generated - 'group_message_sent'
889 * Note: We won't redirect/capture messages in this test because doing so causes message_send() to return early, before
890 * processors and events code is called. We need to test this code here, as we generally redirect messages elsewhere and we
891 * need to be sure this is covered.
893 public function test_message_send_to_conversation_group() {
895 $this->preventResetByRollback();
896 $this->resetAfterTest();
898 $course = $this->getDataGenerator()->create_course();
900 // Create some users and a conversation between them.
901 $user1 = $this->getDataGenerator()->create_user(array('maildisplay' => 1));
902 $user2 = $this->getDataGenerator()->create_user();
903 $user3 = $this->getDataGenerator()->create_user();
904 set_config('allowedemaildomains', 'example.com');
906 // Create a group in the course.
907 $group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id
));
908 groups_add_member($group1->id
, $user1->id
);
909 groups_add_member($group1->id
, $user2->id
);
910 groups_add_member($group1->id
, $user3->id
);
912 $conversation = \core_message\api
::create_conversation(
913 \core_message\api
::MESSAGE_CONVERSATION_TYPE_GROUP
,
914 [$user1->id
, $user2->id
, $user3->id
],
915 'Group project discussion',
916 \core_message\api
::MESSAGE_CONVERSATION_ENABLED
,
920 \context_course
::instance($course->id
)->id
923 // Generate the message.
924 $message = new \core\message\
message();
925 $message->courseid
= 1;
926 $message->component
= 'moodle';
927 $message->name
= 'instantmessage';
928 $message->userfrom
= $user1;
929 $message->convid
= $conversation->id
;
930 $message->subject
= 'message subject 1';
931 $message->fullmessage
= 'message body';
932 $message->fullmessageformat
= FORMAT_MARKDOWN
;
933 $message->fullmessagehtml
= '<p>message body</p>';
934 $message->smallmessage
= 'small message';
935 $message->notification
= '0';
937 // Content specific to the email processor.
938 $content = array('*' => array('header' => ' test ', 'footer' => ' test '));
939 $message->set_additional_content('email', $content);
941 // Ensure the email processor is enabled for the recipient users.
942 $DB->set_field_select('message_processors', 'enabled', 0, "name <> 'email'");
943 set_user_preference('message_provider_moodle_instantmessage_loggedoff', 'email', $user2);
944 set_user_preference('message_provider_moodle_instantmessage_loggedoff', 'email', $user3);
946 // Now, send a message and verify the email processor are hit.
947 $messageid = message_send($message);
949 $sink = $this->redirectEmails();
950 $task = new \message_email\task\
send_email_task();
952 $emails = $sink->get_messages();
953 $this->assertCount(2, $emails);
955 // Verify the record was created in 'messages'.
956 $recordexists = $DB->record_exists('messages', ['id' => $messageid]);
957 $this->assertTrue($recordexists);
959 // Now, send the message again, and verify that the event fired includes the courseid and conversationid.
960 $eventsink = $this->redirectEvents();
961 $messageid = message_send($message);
962 $events = $eventsink->get_events();
963 $this->assertCount(1, $events);
964 $event = reset($events);
965 $this->assertInstanceOf(\core\event\group_message_sent
::class, $event);
966 $this->assertEquals($user1->id
, $event->userid
);
967 $this->assertNull($event->relateduserid
);
968 $this->assertEquals($message->courseid
, $event->other
['courseid']);
969 $this->assertEquals($message->convid
, $event->other
['conversationid']);
975 * Verify that sending a message to a conversation is an action which can be buffered by the manager if in a DB transaction.
977 * This should defer all processor calls (for 2 members in this case), and event creation (1 event).
979 public function test_send_message_to_conversation_group_with_buffering() {
981 $this->preventResetByRollback();
982 $this->resetAfterTest();
984 $course = $this->getDataGenerator()->create_course();
986 $user1 = $this->getDataGenerator()->create_user(array('maildisplay' => 1));
987 $user2 = $this->getDataGenerator()->create_user();
988 $user3 = $this->getDataGenerator()->create_user();
989 set_config('allowedemaildomains', 'example.com');
991 // Create a group in the course.
992 $group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id
));
993 groups_add_member($group1->id
, $user1->id
);
994 groups_add_member($group1->id
, $user2->id
);
995 groups_add_member($group1->id
, $user3->id
);
997 $conversation = \core_message\api
::create_conversation(
998 \core_message\api
::MESSAGE_CONVERSATION_TYPE_GROUP
,
999 [$user1->id
, $user2->id
, $user3->id
],
1000 'Group project discussion',
1001 \core_message\api
::MESSAGE_CONVERSATION_ENABLED
,
1005 \context_course
::instance($course->id
)->id
1008 // Test basic email redirection.
1009 $this->assertFileExists("$CFG->dirroot/message/output/email/version.php");
1010 $this->assertFileExists("$CFG->dirroot/message/output/popup/version.php");
1012 $DB->set_field_select('message_processors', 'enabled', 0, "name <> 'email' AND name <> 'popup'");
1013 get_message_processors(true, true);
1015 $eventsink = $this->redirectEvents();
1017 // Will always use the pop-up processor.
1018 set_user_preference('message_provider_moodle_instantmessage_loggedoff', 'email', $user2);
1019 set_user_preference('message_provider_moodle_instantmessage_loggedoff', 'email', $user3);
1021 $message = new \core\message\
message();
1022 $message->courseid
= 1;
1023 $message->component
= 'moodle';
1024 $message->name
= 'instantmessage';
1025 $message->userfrom
= $user1;
1026 $message->convid
= $conversation->id
;
1027 $message->subject
= 'message subject 1';
1028 $message->fullmessage
= 'message body';
1029 $message->fullmessageformat
= FORMAT_MARKDOWN
;
1030 $message->fullmessagehtml
= '<p>message body</p>';
1031 $message->smallmessage
= 'small message';
1032 $message->notification
= '0';
1034 $transaction = $DB->start_delegated_transaction();
1035 $sink = $this->redirectEmails();
1036 message_send($message);
1037 $emails = $sink->get_messages();
1038 $this->assertCount(0, $emails);
1040 $this->assertFalse($DB->record_exists('message_user_actions', array()));
1041 $events = $eventsink->get_events();
1042 $this->assertCount(0, $events);
1043 $eventsink->clear();
1044 $transaction->allow_commit();
1045 $events = $eventsink->get_events();
1046 $task = new \message_email\task\
send_email_task();
1048 $emails = $sink->get_messages();
1049 $this->assertCount(2, $emails);
1050 $this->assertCount(1, $events);
1051 $this->assertInstanceOf('\core\event\group_message_sent', $events[0]);
1054 public function test_rollback() {
1057 $this->resetAfterTest();
1058 $this->preventResetByRollback();
1060 $user1 = $this->getDataGenerator()->create_user();
1061 $user2 = $this->getDataGenerator()->create_user();
1063 $message = new \core\message\
message();
1064 $message->courseid
= 1;
1065 $message->component
= 'moodle';
1066 $message->name
= 'instantmessage';
1067 $message->userfrom
= $user1;
1068 $message->userto
= $user2;
1069 $message->subject
= 'message subject 1';
1070 $message->fullmessage
= 'message body';
1071 $message->fullmessageformat
= FORMAT_MARKDOWN
;
1072 $message->fullmessagehtml
= '<p>message body</p>';
1073 $message->smallmessage
= 'small message';
1074 $message->notification
= '0';
1076 $mailsink = $this->redirectEmails();
1078 // Sending outside of a transaction is fine.
1079 message_send($message);
1080 $this->assertEquals(1, $mailsink->count());
1082 $transaction1 = $DB->start_delegated_transaction();
1085 message_send($message);
1086 $this->assertEquals(0, $mailsink->count());
1088 $transaction2 = $DB->start_delegated_transaction();
1091 message_send($message);
1092 $this->assertEquals(0, $mailsink->count());
1095 $transaction2->rollback(new \
Exception('x'));
1096 $this->fail('Expecting exception');
1097 } catch (\Exception
$e) {}
1098 $this->assertDebuggingNotCalled();
1099 $this->assertEquals(0, $mailsink->count());
1101 $this->assertTrue($DB->is_transaction_started());
1104 $transaction1->rollback(new \
Exception('x'));
1105 $this->fail('Expecting exception');
1106 } catch (\Exception
$e) {}
1107 $this->assertDebuggingNotCalled();
1108 $this->assertEquals(0, $mailsink->count());
1110 $this->assertFalse($DB->is_transaction_started());
1112 message_send($message);
1113 $this->assertEquals(1, $mailsink->count());
1116 public function test_forced_rollback() {
1119 $this->resetAfterTest();
1120 $this->preventResetByRollback();
1121 set_config('noemailever', 1);
1123 $user1 = $this->getDataGenerator()->create_user();
1124 $user2 = $this->getDataGenerator()->create_user();
1126 $message = new \core\message\
message();
1127 $message->courseid
= 1;
1128 $message->component
= 'moodle';
1129 $message->name
= 'instantmessage';
1130 $message->userfrom
= $user1;
1131 $message->userto
= $user2;
1132 $message->subject
= 'message subject 1';
1133 $message->fullmessage
= 'message body';
1134 $message->fullmessageformat
= FORMAT_MARKDOWN
;
1135 $message->fullmessagehtml
= '<p>message body</p>';
1136 $message->smallmessage
= 'small message';
1137 $message->notification
= '0';
1139 message_send($message);
1140 $this->assertDebuggingCalled('Not sending email due to $CFG->noemailever config setting');
1142 $transaction1 = $DB->start_delegated_transaction();
1144 message_send($message);
1145 $this->assertDebuggingNotCalled();
1147 $transaction2 = $DB->start_delegated_transaction();
1149 message_send($message);
1150 $this->assertDebuggingNotCalled();
1152 $DB->force_transaction_rollback();
1153 $this->assertFalse($DB->is_transaction_started());
1154 $this->assertDebuggingNotCalled();
1156 message_send($message);
1157 $this->assertDebuggingCalled('Not sending email due to $CFG->noemailever config setting');
1160 public function test_message_attachment_send() {
1162 $this->preventResetByRollback();
1163 $this->resetAfterTest();
1165 // Set config setting to allow attachments.
1166 $CFG->allowattachments
= true;
1167 unset_config('noemailever');
1169 $user = $this->getDataGenerator()->create_user();
1170 $context = \context_user
::instance($user->id
);
1172 // Create a test file.
1173 $fs = get_file_storage();
1174 $filerecord = array(
1175 'contextid' => $context->id
,
1176 'component' => 'core',
1177 'filearea' => 'unittest',
1180 'filename' => 'emailtest.txt'
1182 $file = $fs->create_file_from_string($filerecord, 'Test content');
1184 $message = new \core\message\
message();
1185 $message->courseid
= 1;
1186 $message->component
= 'moodle';
1187 $message->name
= 'instantmessage';
1188 $message->userfrom
= get_admin();
1189 $message->userto
= $user;
1190 $message->subject
= 'message subject 1';
1191 $message->fullmessage
= 'message body';
1192 $message->fullmessageformat
= FORMAT_MARKDOWN
;
1193 $message->fullmessagehtml
= '<p>message body</p>';
1194 $message->smallmessage
= 'small message';
1195 $message->attachment
= $file;
1196 $message->attachname
= 'emailtest.txt';
1197 $message->notification
= 0;
1199 // Make sure we are redirecting emails.
1200 $sink = $this->redirectEmails();
1201 message_send($message);
1203 // Get the email that we just sent.
1204 $emails = $sink->get_messages();
1205 $email = reset($emails);
1206 $this->assertTrue(strpos($email->body
, 'Content-Disposition: attachment;') !== false);
1207 $this->assertTrue(strpos($email->body
, 'emailtest.txt') !== false);
1209 // Check if the stored file still exists after remove the temporary attachment.
1210 $storedfileexists = $fs->file_exists($filerecord['contextid'], $filerecord['component'], $filerecord['filearea'],
1211 $filerecord['itemid'], $filerecord['filepath'], $filerecord['filename']);
1212 $this->assertTrue($storedfileexists);
1215 public function test_send_message_when_muted() {
1216 $this->preventResetByRollback();
1217 $this->resetAfterTest();
1219 $userfrom = $this->getDataGenerator()->create_user();
1220 $userto = $this->getDataGenerator()->create_user();
1222 // Create a conversation between the users.
1223 $conversation = \core_message\api
::create_conversation(
1224 \core_message\api
::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL
,
1231 $message = new \core\message\
message();
1232 $message->courseid
= 1;
1233 $message->component
= 'moodle';
1234 $message->name
= 'instantmessage';
1235 $message->userfrom
= $userfrom;
1236 $message->convid
= $conversation->id
;
1237 $message->subject
= 'message subject 1';
1238 $message->fullmessage
= 'message body';
1239 $message->fullmessageformat
= FORMAT_MARKDOWN
;
1240 $message->fullmessagehtml
= '<p>message body</p>';
1241 $message->smallmessage
= 'small message';
1242 $message->notification
= '0';
1244 $sink = $this->redirectEmails();
1245 message_send($message);
1246 $emails = $sink->get_messages();
1247 $this->assertCount(1, $emails);
1250 // Mute the conversation.
1251 \core_message\api
::mute_conversation($userto->id
, $conversation->id
);
1253 $sink = $this->redirectEmails();
1254 message_send($message);
1255 $emails = $sink->get_messages();
1256 $this->assertCount(0, $emails);
1261 * Is a particular message type in the list of message types.
1262 * @param string $component
1263 * @param string $name a message name.
1264 * @param array $providers as returned by message_get_providers_for_user.
1265 * @return bool whether the message type is present.
1267 protected function message_type_present($component, $name, $providers) {
1268 foreach ($providers as $provider) {
1269 if ($provider->component
== $component && $provider->name
== $name) {