/** * Test the message sent event. * * We can not use the message_send() function in the unit test to check that the event was fired as there is a * conditional check to ensure a fake message is sent during unit tests when calling that particular function. */ public function test_message_sent() { $event = \core\event\message_sent::create(array('userid' => 1, 'context' => context_system::instance(), 'relateduserid' => 2, 'other' => array('messageid' => 3))); // Trigger and capturing the event. $sink = $this->redirectEvents(); $event->trigger(); $events = $sink->get_events(); $event = reset($events); // Check that the event data is valid. $this->assertInstanceOf('\\core\\event\\message_sent', $event); $this->assertEquals(context_system::instance(), $event->get_context()); $expected = array(SITEID, 'message', 'write', 'index.php?user=1&id=2&history=1#m3', 1); $this->assertEventLegacyLogData($expected, $event); $url = new moodle_url('/message/index.php', array('user1' => $event->userid, 'user2' => $event->relateduserid)); $this->assertEquals($url, $event->get_url()); }
/** * Called when a message provider wants to send a message. * This functions checks the message recipient's message processor configuration then * sends the message to the configured processors * * Required parameters of the $eventdata object: * component string component name. must exist in message_providers * name string message type name. must exist in message_providers * userfrom object|int the user sending the message * userto object|int the message recipient * subject string the message subject * fullmessage string the full message in a given format * fullmessageformat int the format if the full message (FORMAT_MOODLE, FORMAT_HTML, ..) * fullmessagehtml string the full version (the message processor will choose with one to use) * smallmessage string the small version of the message * * Optional parameters of the $eventdata object: * notification bool should the message be considered as a notification rather than a personal message * contexturl string if this is a notification then you can specify a url to view the event. For example the forum post the user is being notified of. * contexturlname string the display text for contexturl * * @category message * @param object $eventdata information about the message (component, userfrom, userto, ...) * @return mixed the integer ID of the new message or false if there was a problem with a processor */ function message_send($eventdata) { global $CFG, $DB; //new message ID to return $messageid = false; // Fetch default (site) preferences $defaultpreferences = get_message_output_default_preferences(); $preferencebase = $eventdata->component . '_' . $eventdata->name; // If message provider is disabled then don't do any processing. if (!empty($defaultpreferences->{$preferencebase . '_disable'})) { return $messageid; } //TODO: we need to solve problems with database transactions here somehow, for now we just prevent transactions - sorry $DB->transactions_forbidden(); // By default a message is a notification. Only personal/private messages aren't notifications. if (!isset($eventdata->notification)) { $eventdata->notification = 1; } if (is_number($eventdata->userto)) { $eventdata->userto = core_user::get_user($eventdata->userto); } if (is_int($eventdata->userfrom)) { $eventdata->userfrom = core_user::get_user($eventdata->userfrom); } $usertoisrealuser = core_user::is_real_user($eventdata->userto->id) != false; // If recipient is internal user (noreply user), and emailstop is set then don't send any msg. if (!$usertoisrealuser && !empty($eventdata->userto->emailstop)) { debugging('Attempt to send msg to internal (noreply) user', DEBUG_NORMAL); return false; } if (!isset($eventdata->userto->auth) or !isset($eventdata->userto->suspended) or !isset($eventdata->userto->deleted)) { $eventdata->userto = core_user::get_user($eventdata->userto->id); } //after how long inactive should the user be considered logged off? if (isset($CFG->block_online_users_timetosee)) { $timetoshowusers = $CFG->block_online_users_timetosee * 60; } else { $timetoshowusers = 300; //5 minutes } // Work out if the user is logged in or not if (!empty($eventdata->userto->lastaccess) && time() - $timetoshowusers < $eventdata->userto->lastaccess) { $userstate = 'loggedin'; } else { $userstate = 'loggedoff'; } // Create the message object $savemessage = new stdClass(); $savemessage->useridfrom = $eventdata->userfrom->id; $savemessage->useridto = $eventdata->userto->id; $savemessage->subject = $eventdata->subject; $savemessage->fullmessage = $eventdata->fullmessage; $savemessage->fullmessageformat = $eventdata->fullmessageformat; $savemessage->fullmessagehtml = $eventdata->fullmessagehtml; $savemessage->smallmessage = $eventdata->smallmessage; $savemessage->notification = $eventdata->notification; if (!empty($eventdata->contexturl)) { $savemessage->contexturl = $eventdata->contexturl; } else { $savemessage->contexturl = null; } if (!empty($eventdata->contexturlname)) { $savemessage->contexturlname = $eventdata->contexturlname; } else { $savemessage->contexturlname = null; } $savemessage->timecreated = time(); if (PHPUNIT_TEST and class_exists('phpunit_util')) { // Add some more tests to make sure the normal code can actually work. $componentdir = core_component::get_component_directory($eventdata->component); if (!$componentdir or !is_dir($componentdir)) { throw new coding_exception('Invalid component specified in message-send(): ' . $eventdata->component); } if (!file_exists("{$componentdir}/db/messages.php")) { throw new coding_exception("{$eventdata->component} does not contain db/messages.php necessary for message_send()"); } $messageproviders = null; include "{$componentdir}/db/messages.php"; if (!isset($messageproviders[$eventdata->name])) { throw new coding_exception("Missing messaging defaults for event '{$eventdata->name}' in '{$eventdata->component}' messages.php file"); } unset($componentdir); unset($messageproviders); // Now ask phpunit if it wants to catch this message. if (phpunit_util::is_redirecting_messages()) { $savemessage->timeread = time(); $messageid = $DB->insert_record('message_read', $savemessage); $message = $DB->get_record('message_read', array('id' => $messageid)); phpunit_util::message_sent($message); return $messageid; } } // Fetch enabled processors $processors = get_message_processors(true); // Preset variables $processorlist = array(); // Fill in the array of processors to be used based on default and user preferences foreach ($processors as $processor) { // Skip adding processors for internal user, if processor doesn't support sending message to internal user. if (!$usertoisrealuser && !$processor->object->can_send_to_any_users()) { continue; } // First find out permissions $defaultpreference = $processor->name . '_provider_' . $preferencebase . '_permitted'; if (isset($defaultpreferences->{$defaultpreference})) { $permitted = $defaultpreferences->{$defaultpreference}; } else { // MDL-25114 They supplied an $eventdata->component $eventdata->name combination which doesn't // exist in the message_provider table (thus there is no default settings for them). $preferrormsg = "Could not load preference {$defaultpreference}. Make sure the component and name you supplied\n to message_send() are valid."; throw new coding_exception($preferrormsg); } // Find out if user has configured this output // Some processors cannot function without settings from the user $userisconfigured = $processor->object->is_user_configured($eventdata->userto); // DEBUG: notify if we are forcing unconfigured output if ($permitted == 'forced' && !$userisconfigured) { debugging('Attempt to force message delivery to user who has "' . $processor->name . '" output unconfigured', DEBUG_NORMAL); } // Warn developers that necessary data is missing regardless of how the processors are configured if (!isset($eventdata->userto->emailstop)) { debugging('userto->emailstop is not set. Retrieving it from the user table'); $eventdata->userto->emailstop = $DB->get_field('user', 'emailstop', array('id' => $eventdata->userto->id)); } // Populate the list of processors we will be using if ($permitted == 'forced' && $userisconfigured) { // An admin is forcing users to use this message processor. Use this processor unconditionally. $processorlist[] = $processor->name; } else { if ($permitted == 'permitted' && $userisconfigured && !$eventdata->userto->emailstop) { // User has not disabled notifications // See if user set any notification preferences, otherwise use site default ones $userpreferencename = 'message_provider_' . $preferencebase . '_' . $userstate; if ($userpreference = get_user_preferences($userpreferencename, null, $eventdata->userto->id)) { if (in_array($processor->name, explode(',', $userpreference))) { $processorlist[] = $processor->name; } } else { if (isset($defaultpreferences->{$userpreferencename})) { if (in_array($processor->name, explode(',', $defaultpreferences->{$userpreferencename}))) { $processorlist[] = $processor->name; } } } } } } if (empty($processorlist) && $savemessage->notification) { //if they have deselected all processors and its a notification mark it read. The user doesnt want to be bothered $savemessage->timeread = time(); $messageid = $DB->insert_record('message_read', $savemessage); } else { // Process the message // Store unread message just in case we can not send it $messageid = $savemessage->id = $DB->insert_record('message', $savemessage); $eventdata->savedmessageid = $savemessage->id; // Try to deliver the message to each processor if (!empty($processorlist)) { foreach ($processorlist as $procname) { if (!$processors[$procname]->object->send_message($eventdata)) { debugging('Error calling message processor ' . $procname); $messageid = false; } } //if messaging is disabled and they previously had forum notifications handled by the popup processor //or any processor that puts a row in message_working then the notification will remain forever //unread. To prevent this mark the message read if messaging is disabled if (empty($CFG->messaging)) { require_once $CFG->dirroot . '/message/lib.php'; $messageid = message_mark_message_read($savemessage, time()); } else { if ($DB->count_records('message_working', array('unreadmessageid' => $savemessage->id)) == 0) { //if there is no more processors that want to process this we can move message to message_read require_once $CFG->dirroot . '/message/lib.php'; $messageid = message_mark_message_read($savemessage, time(), true); } } } } // We may be sending a message from the 'noreply' address, which means we are not actually sending a // message from a valid user. In this case, we will set the userid to 0. // Check if the userid is valid. if (core_user::is_real_user($eventdata->userfrom->id)) { $userfromid = $eventdata->userfrom->id; } else { $userfromid = 0; } // Trigger event for sending a message. $event = \core\event\message_sent::create(array('userid' => $userfromid, 'context' => context_system::instance(), 'relateduserid' => $eventdata->userto->id, 'other' => array('messageid' => $messageid))); $event->trigger(); return $messageid; }
public function test_mesage_sent_without_other_courseid() { // Creating a message_sent event without other[courseid] leads to exception. $this->expectException('coding_exception'); $this->expectExceptionMessage('The \'courseid\' value must be set in other'); $event = \core\event\message_sent::create(array('userid' => 1, 'context' => context_system::instance(), 'relateduserid' => 2, 'other' => array('messageid' => 3))); }