/** * Generates the message object for a give subscription and event. * * @param int $subscriptionid Subscription instance * @param \stdClass $eventobj Event data * * @return false|\stdClass message object */ protected function generate_message($subscriptionid, \stdClass $eventobj) { try { $subscription = subscription_manager::get_subscription($subscriptionid); } catch (\dml_exception $e) { // Race condition, someone deleted the subscription. return false; } $user = \core_user::get_user($subscription->userid); $context = \context_user::instance($user->id, IGNORE_MISSING); if ($context === false) { // User context doesn't exist. Should never happen, nothing to do return. return false; } $template = $subscription->template; $template = $this->replace_placeholders($template, $subscription, $eventobj, $context); $msgdata = new \stdClass(); $msgdata->component = 'tool_monitor'; // Your component name. $msgdata->name = 'notification'; // This is the message name from messages.php. $msgdata->userfrom = \core_user::get_noreply_user(); $msgdata->userto = $user; $msgdata->subject = $subscription->get_name($context); $msgdata->fullmessage = format_text($template, $subscription->templateformat, array('context' => $context)); $msgdata->fullmessageformat = $subscription->templateformat; $msgdata->fullmessagehtml = format_text($template, $subscription->templateformat, array('context' => $context)); $msgdata->smallmessage = ''; $msgdata->notification = 1; // This is only set to 0 for personal messages between users. return $msgdata; }
/** * Send non-submitters message to students. * * @param string $message * @return void */ public function send_message($userid, $subject, $message) { $eventdata = new stdClass(); $eventdata->component = 'mod_turnitintooltwo'; //your component name $eventdata->name = 'nonsubmitters'; //this is the message name from messages.php $eventdata->userfrom = \core_user::get_noreply_user(); $eventdata->userto = $userid; $eventdata->subject = $subject; $eventdata->fullmessage = $message; $eventdata->fullmessageformat = FORMAT_HTML; $eventdata->fullmessagehtml = $message; $eventdata->smallmessage = ''; $eventdata->notification = 1; //this is only set to 0 for personal messages between users message_send($eventdata); }
public function test_get_user() { global $CFG; $this->resetAfterTest(true); // Create user and try fetach it with api. $user = $this->getDataGenerator()->create_user(); $this->assertEquals($user, core_user::get_user($user->id, '*', MUST_EXIST)); // Test noreply user. $CFG->noreplyuserid = null; $noreplyuser = core_user::get_noreply_user(); $this->assertEquals(1, $noreplyuser->emailstop); $this->assertFalse(core_user::is_real_user($noreplyuser->id)); $this->assertEquals($CFG->noreplyaddress, $noreplyuser->email); $this->assertEquals(get_string('noreplyname'), $noreplyuser->firstname); // Set user as noreply user and make sure noreply propery is set. core_user::reset_internal_users(); $CFG->noreplyuserid = $user->id; $noreplyuser = core_user::get_noreply_user(); $this->assertEquals(1, $noreplyuser->emailstop); $this->assertTrue(core_user::is_real_user($noreplyuser->id)); // Test support user. core_user::reset_internal_users(); $CFG->supportemail = null; $CFG->noreplyuserid = null; $supportuser = core_user::get_support_user(); $adminuser = get_admin(); $this->assertEquals($adminuser, $supportuser); $this->assertTrue(core_user::is_real_user($supportuser->id)); // When supportemail is set. core_user::reset_internal_users(); $CFG->supportemail = '*****@*****.**'; $supportuser = core_user::get_support_user(); $this->assertEquals(core_user::SUPPORT_USER, $supportuser->id); $this->assertFalse(core_user::is_real_user($supportuser->id)); // Set user as support user and make sure noreply propery is set. core_user::reset_internal_users(); $CFG->supportuserid = $user->id; $supportuser = core_user::get_support_user(); $this->assertEquals($user, $supportuser); $this->assertTrue(core_user::is_real_user($supportuser->id)); }
/** * Send instructor message to instructors on course. * * @param array $instructors * @param string $message * @return void */ public function send_instructor_message($instructors, $message) { $subject = get_string('receipt_instructor_copy_subject', 'turnitintooltwo'); $eventdata = new stdClass(); $eventdata->component = 'mod_turnitintooltwo'; //your component name $eventdata->name = 'submission'; //this is the message name from messages.php $eventdata->userfrom = \core_user::get_noreply_user(); $eventdata->subject = $subject; $eventdata->fullmessage = $message; $eventdata->fullmessageformat = FORMAT_HTML; $eventdata->fullmessagehtml = $message; $eventdata->smallmessage = ''; $eventdata->notification = 1; //this is only set to 0 for personal messages between users foreach ($instructors as $instructor) { $eventdata->userto = $instructor->id; message_send($eventdata); } unset($instructor); }
/** * Inform admins about assignments that still need upgrading. */ function mod_assignment_pending_upgrades_notification($count) { $admins = get_admins(); if (empty($admins)) { return; } $a = new stdClass(); $a->count = $count; $a->docsurl = get_docs_url('Assignment_upgrade_tool'); foreach ($admins as $admin) { $message = new stdClass(); $message->component = 'moodle'; $message->name = 'notices'; $message->userfrom = \core_user::get_noreply_user(); $message->userto = $admin; $message->smallmessage = get_string('pendingupgrades_message_small', 'mod_assignment'); $message->subject = get_string('pendingupgrades_message_subject', 'mod_assignment'); $message->fullmessage = get_string('pendingupgrades_message_content', 'mod_assignment', $a); $message->fullmessagehtml = get_string('pendingupgrades_message_content', 'mod_assignment', $a); $message->fullmessageformat = FORMAT_PLAIN; $message->notification = 1; message_send($message); } }
/** * Handle failure of sender verification. * * This will send a notification to the user identified in the Inbound Message address informing them that a message has been * stored. The message includes a verification link and reply-to address which is handled by the * invalid_recipient_handler. * * @param \Horde_Imap_Client_Ids $messageids * @param string $recipient The message recipient * @return bool */ private function handle_verification_failure(\Horde_Imap_Client_Ids $messageids, $recipient) { global $DB, $USER; if (!($messageid = $this->currentmessagedata->messageid)) { mtrace("---> Warning: Unable to determine the Message-ID of the message."); return false; } // Move the message into a new mailbox. $this->client->copy(self::MAILBOX, $this->get_confirmation_folder(), array('create' => true, 'ids' => $messageids, 'move' => true)); // Store the data from the failed message in the associated table. $record = new \stdClass(); $record->messageid = $messageid; $record->userid = $USER->id; $record->address = $recipient; $record->timecreated = time(); $record->id = $DB->insert_record('messageinbound_messagelist', $record); // Setup the Inbound Message generator for the invalid recipient handler. $addressmanager = new \core\message\inbound\address_manager(); $addressmanager->set_handler('\\tool_messageinbound\\message\\inbound\\invalid_recipient_handler'); $addressmanager->set_data($record->id); $eventdata = new \core\message\message(); $eventdata->component = 'tool_messageinbound'; $eventdata->name = 'invalidrecipienthandler'; $userfrom = clone $USER; $userfrom->customheaders = array(); // Adding the In-Reply-To header ensures that it is seen as a reply. $userfrom->customheaders[] = 'In-Reply-To: ' . $messageid; // The message will be sent from the intended user. $eventdata->courseid = SITEID; $eventdata->userfrom = \core_user::get_noreply_user(); $eventdata->userto = $USER; $eventdata->subject = $this->get_reply_subject($this->currentmessagedata->envelope->subject); $eventdata->fullmessage = get_string('invalidrecipientdescription', 'tool_messageinbound', $this->currentmessagedata); $eventdata->fullmessageformat = FORMAT_PLAIN; $eventdata->fullmessagehtml = get_string('invalidrecipientdescriptionhtml', 'tool_messageinbound', $this->currentmessagedata); $eventdata->smallmessage = $eventdata->fullmessage; $eventdata->notification = 1; $eventdata->replyto = $addressmanager->generate($USER->id); mtrace("--> Sending a message to the user to report an verification failure."); if (!message_send($eventdata)) { mtrace("---> Warning: Message could not be sent."); return false; } return true; }
/** * Send the notification message when a quiz attempt becomes overdue. * * @param object $course the course * @param object $quiz the quiz * @param object $attempt this attempt just finished * @param object $context the quiz context * @param object $cm the coursemodule for this quiz */ function quiz_send_overdue_message($course, $quiz, $attempt, $context, $cm) { global $CFG, $DB; // Do nothing if required objects not present. if (empty($course) or empty($quiz) or empty($attempt) or empty($context)) { throw new coding_exception('$course, $quiz, $attempt, $context and $cm must all be set.'); } $submitter = $DB->get_record('user', array('id' => $attempt->userid), '*', MUST_EXIST); if (!has_capability('mod/quiz:emailwarnoverdue', $context, $submitter, false)) { return; // Message not required. } // Prepare lots of useful information that admins might want to include in // the email message. $quizname = format_string($quiz->name); $deadlines = array(); if ($quiz->timelimit) { $deadlines[] = $attempt->timestart + $quiz->timelimit; } if ($quiz->timeclose) { $deadlines[] = $quiz->timeclose; } $duedate = min($deadlines); $graceend = $duedate + $quiz->graceperiod; $a = new stdClass(); // Course info. $a->coursename = $course->fullname; $a->courseshortname = $course->shortname; // Quiz info. $a->quizname = $quizname; $a->quizurl = $CFG->wwwroot . '/mod/quiz/view.php?id=' . $cm->id; $a->quizlink = '<a href="' . $a->quizurl . '">' . $quizname . '</a>'; // Attempt info. $a->attemptduedate = userdate($duedate); $a->attemptgraceend = userdate($graceend); $a->attemptsummaryurl = $CFG->wwwroot . '/mod/quiz/summary.php?attempt=' . $attempt->id; $a->attemptsummarylink = '<a href="' . $a->attemptsummaryurl . '">' . $quizname . ' review</a>'; // Student's info. $a->studentidnumber = $submitter->idnumber; $a->studentname = fullname($submitter); $a->studentusername = $submitter->username; // Prepare the message. $eventdata = new stdClass(); $eventdata->component = 'mod_quiz'; $eventdata->name = 'attempt_overdue'; $eventdata->notification = 1; $eventdata->userfrom = core_user::get_noreply_user(); $eventdata->userto = $submitter; $eventdata->subject = get_string('emailoverduesubject', 'quiz', $a); $eventdata->fullmessage = get_string('emailoverduebody', 'quiz', $a); $eventdata->fullmessageformat = FORMAT_PLAIN; $eventdata->fullmessagehtml = ''; $eventdata->smallmessage = get_string('emailoverduesmall', 'quiz', $a); $eventdata->contexturl = $a->quizurl; $eventdata->contexturlname = $a->quizname; // Send the message. return message_send($eventdata); }
$teacher = false; } $mailstudents = $plugin->get_config('mailstudents'); $mailteachers = $plugin->get_config('mailteachers'); $mailadmins = $plugin->get_config('mailadmins'); $shortname = format_string($course->shortname, true, array('context' => $context)); if (!empty($mailstudents)) { $a = new stdClass(); $a->coursename = format_string($course->fullname, true, array('context' => $coursecontext)); $a->profileurl = "{$CFG->wwwroot}/user/view.php?id={$user->id}"; $eventdata = new \core\message\message(); $eventdata->courseid = $course->id; $eventdata->modulename = 'moodle'; $eventdata->component = 'enrol_paypal'; $eventdata->name = 'paypal_enrolment'; $eventdata->userfrom = empty($teacher) ? core_user::get_noreply_user() : $teacher; $eventdata->userto = $user; $eventdata->subject = get_string("enrolmentnew", 'enrol', $shortname); $eventdata->fullmessage = get_string('welcometocoursetext', '', $a); $eventdata->fullmessageformat = FORMAT_PLAIN; $eventdata->fullmessagehtml = ''; $eventdata->smallmessage = ''; message_send($eventdata); } if (!empty($mailteachers) && !empty($teacher)) { $a->course = format_string($course->fullname, true, array('context' => $coursecontext)); $a->user = fullname($user); $eventdata = new \core\message\message(); $eventdata->courseid = $course->id; $eventdata->modulename = 'moodle'; $eventdata->component = 'enrol_paypal';
/** * Notify student upon successful submission. * * @param stdClass $submission * @return void */ protected function notify_student_submission_receipt(stdClass $submission) { global $DB, $USER; $adminconfig = $this->get_admin_config(); if (empty($adminconfig->submissionreceipts)) { // No need to do anything. return; } if ($submission->userid) { $user = $DB->get_record('user', array('id' => $submission->userid), '*', MUST_EXIST); } else { $user = $USER; } if ($submission->userid == $USER->id) { $this->send_notification(core_user::get_noreply_user(), $user, 'submissionreceipt', 'assign_notification', $submission->timemodified); } else { $this->send_notification($USER, $user, 'submissionreceiptother', 'assign_notification', $submission->timemodified); } }
/** * Function to be run periodically according to the scheduled task. * * Finds all posts that have yet to be mailed out, and mails them * out to all subscribers as well as other maintance tasks. * * NOTE: Since 2.7.2 this function is run by scheduled task rather * than standard cron. * * @todo MDL-44734 The function will be split up into seperate tasks. */ function forum_cron() { global $CFG, $USER, $DB, $PAGE; $site = get_site(); // The main renderers. $htmlout = $PAGE->get_renderer('mod_forum', 'email', 'htmlemail'); $textout = $PAGE->get_renderer('mod_forum', 'email', 'textemail'); $htmldigestfullout = $PAGE->get_renderer('mod_forum', 'emaildigestfull', 'htmlemail'); $textdigestfullout = $PAGE->get_renderer('mod_forum', 'emaildigestfull', 'textemail'); $htmldigestbasicout = $PAGE->get_renderer('mod_forum', 'emaildigestbasic', 'htmlemail'); $textdigestbasicout = $PAGE->get_renderer('mod_forum', 'emaildigestbasic', 'textemail'); // All users that are subscribed to any post that needs sending, // please increase $CFG->extramemorylimit on large sites that // send notifications to a large number of users. $users = array(); $userscount = 0; // Cached user counter - count($users) in PHP is horribly slow!!! // Status arrays. $mailcount = array(); $errorcount = array(); // caches $discussions = array(); $forums = array(); $courses = array(); $coursemodules = array(); $subscribedusers = array(); $messageinboundhandlers = array(); // Posts older than 2 days will not be mailed. This is to avoid the problem where // cron has not been running for a long time, and then suddenly people are flooded // with mail from the past few weeks or months $timenow = time(); $endtime = $timenow - $CFG->maxeditingtime; $starttime = $endtime - 48 * 3600; // Two days earlier // Get the list of forum subscriptions for per-user per-forum maildigest settings. $digestsset = $DB->get_recordset('forum_digests', null, '', 'id, userid, forum, maildigest'); $digests = array(); foreach ($digestsset as $thisrow) { if (!isset($digests[$thisrow->forum])) { $digests[$thisrow->forum] = array(); } $digests[$thisrow->forum][$thisrow->userid] = $thisrow->maildigest; } $digestsset->close(); // Create the generic messageinboundgenerator. $messageinboundgenerator = new \core\message\inbound\address_manager(); $messageinboundgenerator->set_handler('\\mod_forum\\message\\inbound\\reply_handler'); if ($posts = forum_get_unmailed_posts($starttime, $endtime, $timenow)) { // Mark them all now as being mailed. It's unlikely but possible there // might be an error later so that a post is NOT actually mailed out, // but since mail isn't crucial, we can accept this risk. Doing it now // prevents the risk of duplicated mails, which is a worse problem. if (!forum_mark_old_posts_as_mailed($endtime)) { mtrace('Errors occurred while trying to mark some posts as being mailed.'); return false; // Don't continue trying to mail them, in case we are in a cron loop } // checking post validity, and adding users to loop through later foreach ($posts as $pid => $post) { $discussionid = $post->discussion; if (!isset($discussions[$discussionid])) { if ($discussion = $DB->get_record('forum_discussions', array('id' => $post->discussion))) { $discussions[$discussionid] = $discussion; \mod_forum\subscriptions::fill_subscription_cache($discussion->forum); \mod_forum\subscriptions::fill_discussion_subscription_cache($discussion->forum); } else { mtrace('Could not find discussion ' . $discussionid); unset($posts[$pid]); continue; } } $forumid = $discussions[$discussionid]->forum; if (!isset($forums[$forumid])) { if ($forum = $DB->get_record('forum', array('id' => $forumid))) { $forums[$forumid] = $forum; } else { mtrace('Could not find forum ' . $forumid); unset($posts[$pid]); continue; } } $courseid = $forums[$forumid]->course; if (!isset($courses[$courseid])) { if ($course = $DB->get_record('course', array('id' => $courseid))) { $courses[$courseid] = $course; } else { mtrace('Could not find course ' . $courseid); unset($posts[$pid]); continue; } } if (!isset($coursemodules[$forumid])) { if ($cm = get_coursemodule_from_instance('forum', $forumid, $courseid)) { $coursemodules[$forumid] = $cm; } else { mtrace('Could not find course module for forum ' . $forumid); unset($posts[$pid]); continue; } } // Save the Inbound Message datakey here to reduce DB queries later. $messageinboundgenerator->set_data($pid); $messageinboundhandlers[$pid] = $messageinboundgenerator->fetch_data_key(); // Caching subscribed users of each forum. if (!isset($subscribedusers[$forumid])) { $modcontext = context_module::instance($coursemodules[$forumid]->id); if ($subusers = \mod_forum\subscriptions::fetch_subscribed_users($forums[$forumid], 0, $modcontext, 'u.*', true)) { foreach ($subusers as $postuser) { // this user is subscribed to this forum $subscribedusers[$forumid][$postuser->id] = $postuser->id; $userscount++; if ($userscount > FORUM_CRON_USER_CACHE) { // Store minimal user info. $minuser = new stdClass(); $minuser->id = $postuser->id; $users[$postuser->id] = $minuser; } else { // Cache full user record. forum_cron_minimise_user_record($postuser); $users[$postuser->id] = $postuser; } } // Release memory. unset($subusers); unset($postuser); } } $mailcount[$pid] = 0; $errorcount[$pid] = 0; } } if ($users && $posts) { foreach ($users as $userto) { // Terminate if processing of any account takes longer than 2 minutes. core_php_time_limit::raise(120); mtrace('Processing user ' . $userto->id); // Init user caches - we keep the cache for one cycle only, otherwise it could consume too much memory. if (isset($userto->username)) { $userto = clone $userto; } else { $userto = $DB->get_record('user', array('id' => $userto->id)); forum_cron_minimise_user_record($userto); } $userto->viewfullnames = array(); $userto->canpost = array(); $userto->markposts = array(); // Setup this user so that the capabilities are cached, and environment matches receiving user. cron_setup_user($userto); // Reset the caches. foreach ($coursemodules as $forumid => $unused) { $coursemodules[$forumid]->cache = new stdClass(); $coursemodules[$forumid]->cache->caps = array(); unset($coursemodules[$forumid]->uservisible); } foreach ($posts as $pid => $post) { $discussion = $discussions[$post->discussion]; $forum = $forums[$discussion->forum]; $course = $courses[$forum->course]; $cm =& $coursemodules[$forum->id]; // Do some checks to see if we can bail out now. // Only active enrolled users are in the list of subscribers. // This does not necessarily mean that the user is subscribed to the forum or to the discussion though. if (!isset($subscribedusers[$forum->id][$userto->id])) { // The user does not subscribe to this forum. continue; } if (!\mod_forum\subscriptions::is_subscribed($userto->id, $forum, $post->discussion, $coursemodules[$forum->id])) { // The user does not subscribe to this forum, or to this specific discussion. continue; } if ($subscriptiontime = \mod_forum\subscriptions::fetch_discussion_subscription($forum->id, $userto->id)) { // Skip posts if the user subscribed to the discussion after it was created. if (isset($subscriptiontime[$post->discussion]) && $subscriptiontime[$post->discussion] > $post->created) { continue; } } // Don't send email if the forum is Q&A and the user has not posted. // Initial topics are still mailed. if ($forum->type == 'qanda' && !forum_get_user_posted_time($discussion->id, $userto->id) && $pid != $discussion->firstpost) { mtrace('Did not email ' . $userto->id . ' because user has not posted in discussion'); continue; } // Get info about the sending user. if (array_key_exists($post->userid, $users)) { // We might know the user already. $userfrom = $users[$post->userid]; if (!isset($userfrom->idnumber)) { // Minimalised user info, fetch full record. $userfrom = $DB->get_record('user', array('id' => $userfrom->id)); forum_cron_minimise_user_record($userfrom); } } else { if ($userfrom = $DB->get_record('user', array('id' => $post->userid))) { forum_cron_minimise_user_record($userfrom); // Fetch only once if possible, we can add it to user list, it will be skipped anyway. if ($userscount <= FORUM_CRON_USER_CACHE) { $userscount++; $users[$userfrom->id] = $userfrom; } } else { mtrace('Could not find user ' . $post->userid . ', author of post ' . $post->id . '. Unable to send message.'); continue; } } // Note: If we want to check that userto and userfrom are not the same person this is probably the spot to do it. // Setup global $COURSE properly - needed for roles and languages. cron_setup_user($userto, $course); // Fill caches. if (!isset($userto->viewfullnames[$forum->id])) { $modcontext = context_module::instance($cm->id); $userto->viewfullnames[$forum->id] = has_capability('moodle/site:viewfullnames', $modcontext); } if (!isset($userto->canpost[$discussion->id])) { $modcontext = context_module::instance($cm->id); $userto->canpost[$discussion->id] = forum_user_can_post($forum, $discussion, $userto, $cm, $course, $modcontext); } if (!isset($userfrom->groups[$forum->id])) { if (!isset($userfrom->groups)) { $userfrom->groups = array(); if (isset($users[$userfrom->id])) { $users[$userfrom->id]->groups = array(); } } $userfrom->groups[$forum->id] = groups_get_all_groups($course->id, $userfrom->id, $cm->groupingid); if (isset($users[$userfrom->id])) { $users[$userfrom->id]->groups[$forum->id] = $userfrom->groups[$forum->id]; } } // Make sure groups allow this user to see this email. if ($discussion->groupid > 0 and $groupmode = groups_get_activity_groupmode($cm, $course)) { // Groups are being used. if (!groups_group_exists($discussion->groupid)) { // Can't find group - be safe and don't this message. continue; } if (!groups_is_member($discussion->groupid) and !has_capability('moodle/site:accessallgroups', $modcontext)) { // Do not send posts from other groups when in SEPARATEGROUPS or VISIBLEGROUPS. continue; } } // Make sure we're allowed to see the post. if (!forum_user_can_see_post($forum, $discussion, $post, null, $cm)) { mtrace('User ' . $userto->id . ' can not see ' . $post->id . '. Not sending message.'); continue; } // OK so we need to send the email. // Does the user want this post in a digest? If so postpone it for now. $maildigest = forum_get_user_maildigest_bulk($digests, $userto, $forum->id); if ($maildigest > 0) { // This user wants the mails to be in digest form. $queue = new stdClass(); $queue->userid = $userto->id; $queue->discussionid = $discussion->id; $queue->postid = $post->id; $queue->timemodified = $post->created; $DB->insert_record('forum_queue', $queue); continue; } // Prepare to actually send the post now, and build up the content. $cleanforumname = str_replace('"', "'", strip_tags(format_string($forum->name))); $userfrom->customheaders = array('List-Id: "' . $cleanforumname . '" ' . generate_email_messageid('moodleforum' . $forum->id), 'List-Help: ' . $CFG->wwwroot . '/mod/forum/view.php?f=' . $forum->id, 'Message-ID: ' . forum_get_email_message_id($post->id, $userto->id), 'X-Course-Id: ' . $course->id, 'X-Course-Name: ' . format_string($course->fullname, true), 'Precedence: Bulk', 'X-Auto-Response-Suppress: All', 'Auto-Submitted: auto-generated'); $shortname = format_string($course->shortname, true, array('context' => context_course::instance($course->id))); // Generate a reply-to address from using the Inbound Message handler. $replyaddress = null; if ($userto->canpost[$discussion->id] && array_key_exists($post->id, $messageinboundhandlers)) { $messageinboundgenerator->set_data($post->id, $messageinboundhandlers[$post->id]); $replyaddress = $messageinboundgenerator->generate($userto->id); } if (!isset($userto->canpost[$discussion->id])) { $canreply = forum_user_can_post($forum, $discussion, $userto, $cm, $course, $modcontext); } else { $canreply = $userto->canpost[$discussion->id]; } $data = new \mod_forum\output\forum_post_email($course, $cm, $forum, $discussion, $post, $userfrom, $userto, $canreply); $userfrom->customheaders[] = sprintf('List-Unsubscribe: <%s>', $data->get_unsubscribediscussionlink()); if (!isset($userto->viewfullnames[$forum->id])) { $data->viewfullnames = has_capability('moodle/site:viewfullnames', $modcontext, $userto->id); } else { $data->viewfullnames = $userto->viewfullnames[$forum->id]; } // Not all of these variables are used in the default language // string but are made available to support custom subjects. $a = new stdClass(); $a->subject = $data->get_subject(); $a->forumname = $cleanforumname; $a->sitefullname = format_string($site->fullname); $a->siteshortname = format_string($site->shortname); $a->courseidnumber = $data->get_courseidnumber(); $a->coursefullname = $data->get_coursefullname(); $a->courseshortname = $data->get_coursename(); $postsubject = html_to_text(get_string('postmailsubject', 'forum', $a), 0); $rootid = forum_get_email_message_id($discussion->firstpost, $userto->id); if ($post->parent) { // This post is a reply, so add reply header (RFC 2822). $parentid = forum_get_email_message_id($post->parent, $userto->id); $userfrom->customheaders[] = "In-Reply-To: {$parentid}"; // If the post is deeply nested we also reference the parent message id and // the root message id (if different) to aid threading when parts of the email // conversation have been deleted (RFC1036). if ($post->parent != $discussion->firstpost) { $userfrom->customheaders[] = "References: {$rootid} {$parentid}"; } else { $userfrom->customheaders[] = "References: {$parentid}"; } } // MS Outlook / Office uses poorly documented and non standard headers, including // Thread-Topic which overrides the Subject and shouldn't contain Re: or Fwd: etc. $a->subject = $discussion->name; $threadtopic = html_to_text(get_string('postmailsubject', 'forum', $a), 0); $userfrom->customheaders[] = "Thread-Topic: {$threadtopic}"; $userfrom->customheaders[] = "Thread-Index: " . substr($rootid, 1, 28); // Send the post now! mtrace('Sending ', ''); $eventdata = new \core\message\message(); $eventdata->courseid = $course->id; $eventdata->component = 'mod_forum'; $eventdata->name = 'posts'; $eventdata->userfrom = $userfrom; $eventdata->userto = $userto; $eventdata->subject = $postsubject; $eventdata->fullmessage = $textout->render($data); $eventdata->fullmessageformat = FORMAT_PLAIN; $eventdata->fullmessagehtml = $htmlout->render($data); $eventdata->notification = 1; $eventdata->replyto = $replyaddress; if (!empty($replyaddress)) { // Add extra text to email messages if they can reply back. $textfooter = "\n\n" . get_string('replytopostbyemail', 'mod_forum'); $htmlfooter = html_writer::tag('p', get_string('replytopostbyemail', 'mod_forum')); $additionalcontent = array('fullmessage' => array('footer' => $textfooter), 'fullmessagehtml' => array('footer' => $htmlfooter)); $eventdata->set_additional_content('email', $additionalcontent); } $smallmessagestrings = new stdClass(); $smallmessagestrings->user = fullname($userfrom); $smallmessagestrings->forumname = "{$shortname}: " . format_string($forum->name, true) . ": " . $discussion->name; $smallmessagestrings->message = $post->message; // Make sure strings are in message recipients language. $eventdata->smallmessage = get_string_manager()->get_string('smallmessage', 'forum', $smallmessagestrings, $userto->lang); $contexturl = new moodle_url('/mod/forum/discuss.php', array('d' => $discussion->id), 'p' . $post->id); $eventdata->contexturl = $contexturl->out(); $eventdata->contexturlname = $discussion->name; $mailresult = message_send($eventdata); if (!$mailresult) { mtrace("Error: mod/forum/lib.php forum_cron(): Could not send out mail for id {$post->id} to user {$userto->id}" . " ({$userto->email}) .. not trying again."); $errorcount[$post->id]++; } else { $mailcount[$post->id]++; // Mark post as read if forum_usermarksread is set off. if (!$CFG->forum_usermarksread) { $userto->markposts[$post->id] = $post->id; } } mtrace('post ' . $post->id . ': ' . $post->subject); } // Mark processed posts as read. if (get_user_preferences('forum_markasreadonnotification', 1, $userto->id) == 1) { forum_tp_mark_posts_read($userto, $userto->markposts); } unset($userto); } } if ($posts) { foreach ($posts as $post) { mtrace($mailcount[$post->id] . " users were sent post {$post->id}, '{$post->subject}'"); if ($errorcount[$post->id]) { $DB->set_field('forum_posts', 'mailed', FORUM_MAILED_ERROR, array('id' => $post->id)); } } } // release some memory unset($subscribedusers); unset($mailcount); unset($errorcount); cron_setup_user(); $sitetimezone = core_date::get_server_timezone(); // Now see if there are any digest mails waiting to be sent, and if we should send them mtrace('Starting digest processing...'); core_php_time_limit::raise(300); // terminate if not able to fetch all digests in 5 minutes if (!isset($CFG->digestmailtimelast)) { // To catch the first time set_config('digestmailtimelast', 0); } $timenow = time(); $digesttime = usergetmidnight($timenow, $sitetimezone) + $CFG->digestmailtime * 3600; // Delete any really old ones (normally there shouldn't be any) $weekago = $timenow - 7 * 24 * 3600; $DB->delete_records_select('forum_queue', "timemodified < ?", array($weekago)); mtrace('Cleaned old digest records'); if ($CFG->digestmailtimelast < $digesttime and $timenow > $digesttime) { mtrace('Sending forum digests: ' . userdate($timenow, '', $sitetimezone)); $digestposts_rs = $DB->get_recordset_select('forum_queue', "timemodified < ?", array($digesttime)); if ($digestposts_rs->valid()) { // We have work to do $usermailcount = 0; //caches - reuse the those filled before too $discussionposts = array(); $userdiscussions = array(); foreach ($digestposts_rs as $digestpost) { if (!isset($posts[$digestpost->postid])) { if ($post = $DB->get_record('forum_posts', array('id' => $digestpost->postid))) { $posts[$digestpost->postid] = $post; } else { continue; } } $discussionid = $digestpost->discussionid; if (!isset($discussions[$discussionid])) { if ($discussion = $DB->get_record('forum_discussions', array('id' => $discussionid))) { $discussions[$discussionid] = $discussion; } else { continue; } } $forumid = $discussions[$discussionid]->forum; if (!isset($forums[$forumid])) { if ($forum = $DB->get_record('forum', array('id' => $forumid))) { $forums[$forumid] = $forum; } else { continue; } } $courseid = $forums[$forumid]->course; if (!isset($courses[$courseid])) { if ($course = $DB->get_record('course', array('id' => $courseid))) { $courses[$courseid] = $course; } else { continue; } } if (!isset($coursemodules[$forumid])) { if ($cm = get_coursemodule_from_instance('forum', $forumid, $courseid)) { $coursemodules[$forumid] = $cm; } else { continue; } } $userdiscussions[$digestpost->userid][$digestpost->discussionid] = $digestpost->discussionid; $discussionposts[$digestpost->discussionid][$digestpost->postid] = $digestpost->postid; } $digestposts_rs->close(); /// Finished iteration, let's close the resultset // Data collected, start sending out emails to each user foreach ($userdiscussions as $userid => $thesediscussions) { core_php_time_limit::raise(120); // terminate if processing of any account takes longer than 2 minutes cron_setup_user(); mtrace(get_string('processingdigest', 'forum', $userid), '... '); // First of all delete all the queue entries for this user $DB->delete_records_select('forum_queue', "userid = ? AND timemodified < ?", array($userid, $digesttime)); // Init user caches - we keep the cache for one cycle only, // otherwise it would unnecessarily consume memory. if (array_key_exists($userid, $users) and isset($users[$userid]->username)) { $userto = clone $users[$userid]; } else { $userto = $DB->get_record('user', array('id' => $userid)); forum_cron_minimise_user_record($userto); } $userto->viewfullnames = array(); $userto->canpost = array(); $userto->markposts = array(); // Override the language and timezone of the "current" user, so that // mail is customised for the receiver. cron_setup_user($userto); $postsubject = get_string('digestmailsubject', 'forum', format_string($site->shortname, true)); $headerdata = new stdClass(); $headerdata->sitename = format_string($site->fullname, true); $headerdata->userprefs = $CFG->wwwroot . '/user/forum.php?id=' . $userid . '&course=' . $site->id; $posttext = get_string('digestmailheader', 'forum', $headerdata) . "\n\n"; $headerdata->userprefs = '<a target="_blank" href="' . $headerdata->userprefs . '">' . get_string('digestmailprefs', 'forum') . '</a>'; $posthtml = '<p>' . get_string('digestmailheader', 'forum', $headerdata) . '</p>' . '<br /><hr size="1" noshade="noshade" />'; foreach ($thesediscussions as $discussionid) { core_php_time_limit::raise(120); // to be reset for each post $discussion = $discussions[$discussionid]; $forum = $forums[$discussion->forum]; $course = $courses[$forum->course]; $cm = $coursemodules[$forum->id]; //override language cron_setup_user($userto, $course); // Fill caches if (!isset($userto->viewfullnames[$forum->id])) { $modcontext = context_module::instance($cm->id); $userto->viewfullnames[$forum->id] = has_capability('moodle/site:viewfullnames', $modcontext); } if (!isset($userto->canpost[$discussion->id])) { $modcontext = context_module::instance($cm->id); $userto->canpost[$discussion->id] = forum_user_can_post($forum, $discussion, $userto, $cm, $course, $modcontext); } $strforums = get_string('forums', 'forum'); $canunsubscribe = !\mod_forum\subscriptions::is_forcesubscribed($forum); $canreply = $userto->canpost[$discussion->id]; $shortname = format_string($course->shortname, true, array('context' => context_course::instance($course->id))); $posttext .= "\n \n"; $posttext .= '====================================================================='; $posttext .= "\n \n"; $posttext .= "{$shortname} -> {$strforums} -> " . format_string($forum->name, true); if ($discussion->name != $forum->name) { $posttext .= " -> " . format_string($discussion->name, true); } $posttext .= "\n"; $posttext .= $CFG->wwwroot . '/mod/forum/discuss.php?d=' . $discussion->id; $posttext .= "\n"; $posthtml .= "<p><font face=\"sans-serif\">" . "<a target=\"_blank\" href=\"{$CFG->wwwroot}/course/view.php?id={$course->id}\">{$shortname}</a> -> " . "<a target=\"_blank\" href=\"{$CFG->wwwroot}/mod/forum/index.php?id={$course->id}\">{$strforums}</a> -> " . "<a target=\"_blank\" href=\"{$CFG->wwwroot}/mod/forum/view.php?f={$forum->id}\">" . format_string($forum->name, true) . "</a>"; if ($discussion->name == $forum->name) { $posthtml .= "</font></p>"; } else { $posthtml .= " -> <a target=\"_blank\" href=\"{$CFG->wwwroot}/mod/forum/discuss.php?d={$discussion->id}\">" . format_string($discussion->name, true) . "</a></font></p>"; } $posthtml .= '<p>'; $postsarray = $discussionposts[$discussionid]; sort($postsarray); $sentcount = 0; foreach ($postsarray as $postid) { $post = $posts[$postid]; if (array_key_exists($post->userid, $users)) { // we might know him/her already $userfrom = $users[$post->userid]; if (!isset($userfrom->idnumber)) { $userfrom = $DB->get_record('user', array('id' => $userfrom->id)); forum_cron_minimise_user_record($userfrom); } } else { if ($userfrom = $DB->get_record('user', array('id' => $post->userid))) { forum_cron_minimise_user_record($userfrom); if ($userscount <= FORUM_CRON_USER_CACHE) { $userscount++; $users[$userfrom->id] = $userfrom; } } else { mtrace('Could not find user ' . $post->userid); continue; } } if (!isset($userfrom->groups[$forum->id])) { if (!isset($userfrom->groups)) { $userfrom->groups = array(); if (isset($users[$userfrom->id])) { $users[$userfrom->id]->groups = array(); } } $userfrom->groups[$forum->id] = groups_get_all_groups($course->id, $userfrom->id, $cm->groupingid); if (isset($users[$userfrom->id])) { $users[$userfrom->id]->groups[$forum->id] = $userfrom->groups[$forum->id]; } } // Headers to help prevent auto-responders. $userfrom->customheaders = array("Precedence: Bulk", 'X-Auto-Response-Suppress: All', 'Auto-Submitted: auto-generated'); $maildigest = forum_get_user_maildigest_bulk($digests, $userto, $forum->id); if (!isset($userto->canpost[$discussion->id])) { $canreply = forum_user_can_post($forum, $discussion, $userto, $cm, $course, $modcontext); } else { $canreply = $userto->canpost[$discussion->id]; } $data = new \mod_forum\output\forum_post_email($course, $cm, $forum, $discussion, $post, $userfrom, $userto, $canreply); if (!isset($userto->viewfullnames[$forum->id])) { $data->viewfullnames = has_capability('moodle/site:viewfullnames', $modcontext, $userto->id); } else { $data->viewfullnames = $userto->viewfullnames[$forum->id]; } if ($maildigest == 2) { // Subjects and link only. $posttext .= $textdigestbasicout->render($data); $posthtml .= $htmldigestbasicout->render($data); } else { // The full treatment. $posttext .= $textdigestfullout->render($data); $posthtml .= $htmldigestfullout->render($data); // Create an array of postid's for this user to mark as read. if (!$CFG->forum_usermarksread) { $userto->markposts[$post->id] = $post->id; } } $sentcount++; } $footerlinks = array(); if ($canunsubscribe) { $footerlinks[] = "<a href=\"{$CFG->wwwroot}/mod/forum/subscribe.php?id={$forum->id}\">" . get_string("unsubscribe", "forum") . "</a>"; } else { $footerlinks[] = get_string("everyoneissubscribed", "forum"); } $footerlinks[] = "<a href='{$CFG->wwwroot}/mod/forum/index.php?id={$forum->course}'>" . get_string("digestmailpost", "forum") . '</a>'; $posthtml .= "\n<div class='mdl-right'><font size=\"1\">" . implode(' ', $footerlinks) . '</font></div>'; $posthtml .= '<hr size="1" noshade="noshade" /></p>'; } if (empty($userto->mailformat) || $userto->mailformat != 1) { // This user DOESN'T want to receive HTML $posthtml = ''; } $eventdata = new \core\message\message(); $eventdata->courseid = SITEID; $eventdata->component = 'mod_forum'; $eventdata->name = 'digests'; $eventdata->userfrom = core_user::get_noreply_user(); $eventdata->userto = $userto; $eventdata->subject = $postsubject; $eventdata->fullmessage = $posttext; $eventdata->fullmessageformat = FORMAT_PLAIN; $eventdata->fullmessagehtml = $posthtml; $eventdata->notification = 1; $eventdata->smallmessage = get_string('smallmessagedigest', 'forum', $sentcount); $mailresult = message_send($eventdata); if (!$mailresult) { mtrace("ERROR: mod/forum/cron.php: Could not send out digest mail to user {$userto->id} " . "({$userto->email})... not trying again."); } else { mtrace("success."); $usermailcount++; // Mark post as read if forum_usermarksread is set off if (get_user_preferences('forum_markasreadonnotification', 1, $userto->id) == 1) { forum_tp_mark_posts_read($userto, $userto->markposts); } } } } /// We have finishied all digest emails, update $CFG->digestmailtimelast set_config('digestmailtimelast', $timenow); } cron_setup_user(); if (!empty($usermailcount)) { mtrace(get_string('digestsentusers', 'forum', $usermailcount)); } if (!empty($CFG->forum_lastreadclean)) { $timenow = time(); if ($CFG->forum_lastreadclean + 24 * 3600 < $timenow) { set_config('forum_lastreadclean', $timenow); mtrace('Removing old forum read tracking info...'); forum_tp_clean_read_records(); } } else { set_config('forum_lastreadclean', time()); } return true; }
/** * Commenting on a plan. */ public function test_comment_add_plan() { $this->resetAfterTest(); $dg = $this->getDataGenerator(); $lpg = $dg->get_plugin_generator('core_competency'); $u1 = $dg->create_user(); $u2 = $dg->create_user(); $u3 = $dg->create_user(); $userroleid = $dg->create_role(); $reviewerroleid = $dg->create_role(); assign_capability('moodle/competency:planviewowndraft', CAP_ALLOW, $userroleid, context_system::instance()->id, true); assign_capability('moodle/competency:planviewown', CAP_ALLOW, $userroleid, context_system::instance()->id, true); assign_capability('moodle/competency:planviewdraft', CAP_ALLOW, $reviewerroleid, context_system::instance()->id, true); assign_capability('moodle/competency:planmanage', CAP_ALLOW, $reviewerroleid, context_system::instance()->id, true); assign_capability('moodle/competency:plancomment', CAP_ALLOW, $reviewerroleid, context_system::instance()->id, true); $dg->role_assign($userroleid, $u1->id, context_user::instance($u1->id)); $dg->role_assign($reviewerroleid, $u2->id, context_user::instance($u1->id)); $dg->role_assign($reviewerroleid, $u3->id, context_system::instance()); accesslib_clear_all_caches_for_unit_testing(); $p1 = $lpg->create_plan(array('userid' => $u1->id)); // Post a comment in own plan, no reviewer. Nobody is messaged. $this->setUser($u1); $comment = $p1->get_comment_object(); $sink = $this->redirectMessages(); $comment->add('Hello world!'); $messages = $sink->get_messages(); $sink->close(); $this->assertCount(0, $messages); // Post a comment in plan as someone else, no reviewer. The owner is messages. $this->setUser($u3); $comment = $p1->get_comment_object(); $sink = $this->redirectMessages(); $comment->add('Hello world!'); $messages = $sink->get_messages(); $sink->close(); $this->assertCount(1, $messages); $message = array_pop($messages); $this->assertEquals(core_user::get_noreply_user()->id, $message->useridfrom); $this->assertEquals($u1->id, $message->useridto); // Post a comment in a plan with reviewer. The reviewer is messaged. $p1->set_reviewerid($u2->id); $p1->update(); $this->setUser($u1); $comment = $p1->get_comment_object(); $sink = $this->redirectMessages(); $comment->add('Hello world!'); $messages = $sink->get_messages(); $sink->close(); $this->assertCount(1, $messages); $message = array_pop($messages); $this->assertEquals(core_user::get_noreply_user()->id, $message->useridfrom); $this->assertEquals($u2->id, $message->useridto); // Post a comment as reviewer in a plan being reviewed. The owner is messaged. $p1->set_reviewerid($u2->id); $p1->update(); $this->setUser($u2); $comment = $p1->get_comment_object(); $sink = $this->redirectMessages(); $comment->add('Hello world!'); $messages = $sink->get_messages(); $sink->close(); $this->assertCount(1, $messages); $message = array_pop($messages); $this->assertEquals(core_user::get_noreply_user()->id, $message->useridfrom); $this->assertEquals($u1->id, $message->useridto); // Post a comment as someone else in a plan being reviewed. The owner and reviewer are messaged. $p1->set_reviewerid($u2->id); $p1->update(); $this->setUser($u3); $comment = $p1->get_comment_object(); $sink = $this->redirectMessages(); $comment->add('Hello world!'); $messages = $sink->get_messages(); $sink->close(); $this->assertCount(2, $messages); $message1 = array_shift($messages); $message2 = array_shift($messages); $this->assertEquals(core_user::get_noreply_user()->id, $message1->useridfrom); $this->assertEquals($u1->id, $message1->useridto); $this->assertEquals(core_user::get_noreply_user()->id, $message2->useridfrom); $this->assertEquals($u2->id, $message2->useridto); $p1->set_reviewerid(null); $p1->update(); // Test message content. $this->setUser($u3); $comment = $p1->get_comment_object(); $sink = $this->redirectMessages(); $comment->add('Hello world!'); $messages = $sink->get_messages(); $sink->close(); $this->assertCount(1, $messages); $message = array_pop($messages); $expectedurlname = $p1->get_name(); $expectedurl = url::plan($p1->get_id()); $this->assertTrue(strpos($message->fullmessage, 'Hello world!') !== false); $this->assertTrue(strpos($message->fullmessagehtml, 'Hello world!') !== false); $this->assertEquals(FORMAT_MOODLE, $message->fullmessageformat); $this->assertEquals($expectedurl->out(false), $message->contexturl); $this->assertEquals($expectedurlname, $message->contexturlname); // Test message content as HTML. $this->setUser($u3); $comment = $p1->get_comment_object(); $sink = $this->redirectMessages(); $comment->add('<em>Hello world!</em>', FORMAT_HTML); $messages = $sink->get_messages(); $sink->close(); $this->assertCount(1, $messages); $message = array_pop($messages); $expectedurlname = $p1->get_name(); $expectedurl = url::plan($p1->get_id()); $this->assertTrue(strpos($message->fullmessage, '<em>Hello world!</em>') !== false); $this->assertTrue(strpos($message->fullmessagehtml, '<em>Hello world!</em>') !== false); $this->assertEquals(FORMAT_HTML, $message->fullmessageformat); $this->assertEquals($expectedurl->out(false), $message->contexturl); $this->assertEquals($expectedurlname, $message->contexturlname); }
/** * Test require_active_user */ public function test_require_active_user() { global $DB; // Create a default user for the test. $userexpected = $this->getDataGenerator()->create_user(); // Simple case, all good. core_user::require_active_user($userexpected, true, true); // Set user not confirmed. $DB->set_field('user', 'confirmed', 0, array('id' => $userexpected->id)); try { core_user::require_active_user($userexpected); } catch (moodle_exception $e) { $this->assertEquals('usernotconfirmed', $e->errorcode); } $DB->set_field('user', 'confirmed', 1, array('id' => $userexpected->id)); // Set nologin auth method. $DB->set_field('user', 'auth', 'nologin', array('id' => $userexpected->id)); try { core_user::require_active_user($userexpected, false, true); } catch (moodle_exception $e) { $this->assertEquals('suspended', $e->errorcode); } // Check no exceptions are thrown if we don't specify to check suspended. core_user::require_active_user($userexpected); $DB->set_field('user', 'auth', 'manual', array('id' => $userexpected->id)); // Set user suspended. $DB->set_field('user', 'suspended', 1, array('id' => $userexpected->id)); try { core_user::require_active_user($userexpected, true); } catch (moodle_exception $e) { $this->assertEquals('suspended', $e->errorcode); } // Check no exceptions are thrown if we don't specify to check suspended. core_user::require_active_user($userexpected); // Delete user. delete_user($userexpected); try { core_user::require_active_user($userexpected); } catch (moodle_exception $e) { $this->assertEquals('userdeleted', $e->errorcode); } // Use a not real user. $noreplyuser = core_user::get_noreply_user(); try { core_user::require_active_user($noreplyuser, true); } catch (moodle_exception $e) { $this->assertEquals('invaliduser', $e->errorcode); } // Get the guest user. $guestuser = $DB->get_record('user', array('username' => 'guest')); try { core_user::require_active_user($guestuser, true); } catch (moodle_exception $e) { $this->assertEquals('guestsarenotallowed', $e->errorcode); } }
function local_uai_send_notifications($cron = true, $debug = false, $debugsend = false, $course = 0) { global $DB, $USER; // Get the notifications configured if ($course) { $quiznotifications = $DB->get_records('local_uai_quiz_notifications', array('course' => $course)); } else { $quiznotifications = $DB->get_records('local_uai_quiz_notifications'); } $numnotifications = count($quiznotifications); // If there are any if ($numnotifications > 0) { // Process each course separatedly foreach ($quiznotifications as $quiznotification) { if (!($course = $DB->get_record('course', array('id' => $quiznotification->course)))) { $msg = 'Invalid course id ' . $quiznotification->course; if ($cron) { mtrace($msg); } else { if ($debug) { echo $msg; } } continue; } $msg = 'Processing notifications for course ' . $course->fullname; if ($cron) { mtrace($msg); } else { if ($debug) { echo $msg; } } // Get the attempts $attemptsSemester = local_uai_get_quiz_attempts($course->id, -365); // Calculate stats for the attempts list($studentinfoSemester, $coursestatsSemester) = local_uai_get_stats_from_attempts($attemptsSemester); // Get the attempts $attempts = local_uai_get_quiz_attempts($course->id, -7); $userfrom = \core_user::get_noreply_user(); $userfrom->maildisplay = true; $totalmessages = 1; foreach ($attempts as $studentinfo) { // The user to be notified if ($debugsend) { $userto = $DB->get_record('user', array('id' => $USER->id)); } else { $userto = $DB->get_record('user', array('id' => $studentinfo->uid)); } // Email subject $subject = 'Informe de tu trabajo on-line'; $message = '<html>'; $message .= '<p><strong>Estimado(a) ' . $studentinfo->firstname . ' ' . $studentinfo->lastname . '</strong>,</p>'; $message .= '<p>Quiero que notes que respecto de tu trabajo con los ejercicios de wiris:</p>'; $message .= '<p>Esta semana realizaste ' . $studentinfo->finished . ' intentos'; if ($studentinfo->correct > 0) { $message .= ', de los cuales contestaste adecuadamente ' . $studentinfo->correct; } $message .= '.<br/>'; $message .= 'Desde el inicio del curso hasta ahora llevas acumulado un trabajo de ' . $studentinfoSemester[$studentinfo->uid]->finished . ' intentos y en promedio un '; $message .= 'alumno del curso ha trabajado ' . $coursestatsSemester->avgfinished . ', con un máximo de ' . $coursestatsSemester->maxfinished . ' intentos.</p><br/><br/>'; $message .= 'Quedo en espera de tus dudas.'; $message .= '</html>'; $eventdata = new stdClass(); $eventdata->component = 'local_uai'; $eventdata->name = 'quizzes_notification'; $eventdata->userto = $userto; $eventdata->userfrom = $userfrom; $eventdata->subject = $subject; $eventdata->fullmessage = format_text_email($message, FORMAT_HTML); $eventdata->fullmessageformat = FORMAT_HTML; $eventdata->fullmessagehtml = $message; $eventdata->smallmessage = $subject; $eventdata->notification = 1; // this is only set to 0 for personal messages between users if ($userto) { if (!$debug || $debugsend) { $send = message_send($eventdata); } if ($debug) { echo '<hr>'; echo 'Subject: ' . $subject . '<br/>'; echo "To: {$userto->firstname} {$userto->lastname} <{$userto->email}><br/>"; echo $message; } $totalmessages++; } else { if ($cron) { mtrace("Error sending message to {$userto}"); } } if ($debugsend) { break; } } } } return array($totalmessages, $numnotifications); }
/** * unregisters/unqueues a user from a certain active-group * * @param int $agrpid active-group-id to unregister/unqueue user from * @param int $userid user to unregister/unqueue * @param bool $previewonly optional don't act, just return a preview * @return array ($error, $message) */ private function unregister_from_agrp($agrpid = 0, $userid = 0, $previewonly = false) { global $USER, $PAGE, $DB, $CFG; if (empty($agrpid)) { print_error('missing_param', null, $PAGE->url); } if (empty($userid)) { $userid = $USER->id; require_capability('mod/grouptool:register', $this->context); } $regopen = $this->grouptool->allow_reg && ($this->grouptool->timedue == 0 || time() < $this->grouptool->timedue); if (!$regopen && !has_capability('mod/grouptool:register_students', $this->context)) { return array(true, get_string('reg_not_open', 'grouptool')); } if (empty($this->grouptool->allow_unreg)) { return array(true, get_string('unreg_not_allowed', 'grouptool')); } $message = new stdClass(); if ($userid != $USER->id) { $userdata = $DB->get_record('user', array('id' => $userid)); $message->username = fullname($userdata); } $groupdata = $this->get_active_groups(true, true, $agrpid); $groupdata = reset($groupdata); $message->groupname = $groupdata->name; $agrpids = $DB->get_fieldset_select('grouptool_agrps', 'id', "grouptoolid = ?", array($this->grouptool->id)); list($agrpsql, $params) = $DB->get_in_or_equal($agrpids); array_unshift($params, $userid); $userregs = $DB->count_records_select('grouptool_registered', "modified_by >= 0 AND userid = ? AND agrpid " . $agrpsql, $params); $userqueues = $DB->count_records_select('grouptool_queued', "userid = ? AND agrpid " . $agrpsql, $params); $max = $this->grouptool->allow_multiple ? $this->grouptool->choose_max : 1; $min = $this->grouptool->allow_multiple ? $this->grouptool->choose_min : 0; if ($userregs + $userqueues <= $min) { if ($userid == $USER->id) { return array(true, get_string('you_have_too_less_regs', 'grouptool', $message)); } else { return array(true, get_string('user_has_too_less_regs', 'grouptool', $message)); } } if ($groupdata) { if ($this->get_rank_in_queue($groupdata->registered, $userid) != false) { // He is registered! if ($previewonly) { if ($userid == $USER->id) { return array(false, get_string('unreg_you_from_group', 'grouptool', $message)); } else { return array(false, get_string('unreg_from_group', 'grouptool', $message)); } } else { $records = $DB->get_records('grouptool_registered', array('agrpid' => $agrpid, 'userid' => $userid)); $DB->delete_records('grouptool_registered', array('agrpid' => $agrpid, 'userid' => $userid)); if (!empty($this->grouptool->immediate_reg)) { groups_remove_member($groupdata->id, $userid); } foreach ($records as $data) { // Trigger the event! $data->groupid = $groupdata->id; \mod_grouptool\event\registration_deleted::create_direct($this->cm, $data)->trigger(); } // Get next queued user and put him in the group (and delete queue entry)! if (!empty($this->grouptool->use_queue) && !empty($groupdata->queued)) { $sql = "SELECT queued.*, agrp.groupid\n FROM {grouptool_queued} queued\n JOIN {grouptool_agrps} agrp ON agrp.id = queued.agrpid\n WHERE agrpid = ?\n ORDER BY timestamp ASC\n LIMIT 1"; $record = $DB->get_record_sql($sql, array($agrpid)); $newrecord = clone $record; unset($newrecord->id); $newrecord->modified_by = $newrecord->userid; $newrecord->id = $DB->insert_record('grouptool_registered', $newrecord); if (!empty($this->grouptool->immediate_reg)) { groups_add_member($groupdata->id, $newrecord->userid); } $allowm = $this->grouptool->allow_multiple; $usrregcnt = $this->get_user_reg_count(0, $newrecord->userid); $max = $this->grouptool->choose_max; if ($allowm && $usrregcnt >= $max || !$allowm) { $agrps = $this->get_active_groups(false, false, 0, 0, 0, false); $agrpids = array_keys($agrps); list($sql, $params) = $DB->get_in_or_equal($agrpids); $records = $DB->get_records_sql("SELECT queued.*, agrp.groupid\n FROM {grouptool_queued} queued\n JOIN {grouptool_agrps} agrp ON queued.agrpid = agrp.id\n WHERE userid = ? AND agrpid " . $sql, array_merge(array($newrecord->userid), $params)); $DB->delete_records_select('grouptool_queued', ' userid = ? AND agrpid ' . $sql, array_merge(array($newrecord->userid), $params)); foreach ($records as $cur) { // Trigger the event! \mod_grouptool\event\queue_entry_deleted::create_limit_violation($this->cm, $cur)->trigger(); } } $strgrouptools = get_string("modulenameplural", "grouptool"); $strgrouptool = get_string("modulename", "grouptool"); $postsubject = $this->course->shortname . ': ' . $strgrouptools . ': ' . format_string($this->grouptool->name, true); $posttext = $this->course->shortname . ' -> ' . $strgrouptools . ' -> ' . format_string($this->grouptool->name, true) . "\n"; $posttext .= "----------------------------------------------------------\n"; $posttext .= get_string("register_you_in_group_successmail", "grouptool", $message) . "\n"; $posttext .= "----------------------------------------------------------\n"; $usermailformat = $DB->get_field('user', 'mailformat', array('id' => $newrecord->userid)); if ($usermailformat == 1) { // HTML! $posthtml = "<p><font face=\"sans-serif\">"; $posthtml = "<a href=\"" . $CFG->wwwroot . "/course/view.php?id=" . $this->course->id . "\">" . $this->course->shortname . "</a> ->"; $posthtml = "<a href=\"" . $CFG->wwwroot . "/mod/grouptool/index.php?id=" . $this->course->id . "\">" . $strgrouptools . "</a> ->"; $posthtml = "<a href=\"" . $CFG->wwwroot . "/mod/grouptool/view.php?id=" . $this->cm->id . "\">" . format_string($this->grouptool->name, true) . "</a></font></p>"; $posthtml .= "<hr /><font face=\"sans-serif\">"; $posthtml .= "<p>" . get_string("register_you_in_group_successmailhtml", "grouptool", $message) . "</p>"; $posthtml .= "</font><hr />"; } else { $posthtml = ""; } $messageuser = $DB->get_record('user', array('id' => $newrecord->userid)); $eventdata = new stdClass(); $eventdata->modulename = 'grouptool'; $userfrom = core_user::get_noreply_user(); $eventdata->userfrom = $userfrom; $eventdata->userto = $messageuser; $eventdata->subject = $postsubject; $eventdata->fullmessage = $posttext; $eventdata->fullmessageformat = FORMAT_PLAIN; $eventdata->fullmessagehtml = $posthtml; $eventdata->smallmessage = get_string('register_you_in_group_success', 'grouptool', $message); $eventdata->name = 'grouptool_moveupreg'; $eventdata->component = 'mod_grouptool'; $eventdata->notification = 1; $eventdata->contexturl = $CFG->wwwroot . '/mod/grouptool/view.php?id=' . $this->cm->id; $eventdata->contexturlname = $this->grouptool->name; message_send($eventdata); $DB->delete_records('grouptool_queued', array('id' => $record->id)); // Trigger the event! // We fetched groupid above in SQL. \mod_grouptool\event\user_moved::promotion_from_queue($this->cm, $record, $newrecord)->trigger(); } if ($userid == $USER->id) { return array(false, get_string('unreg_you_from_group_success', 'grouptool', $message)); } else { return array(false, get_string('unreg_from_group_success', 'grouptool', $message)); } } } else { if ($this->get_rank_in_queue($groupdata->queued, $userid) != false) { // He is queued! if ($previewonly) { if ($userid == $USER->id) { return array(false, get_string('unqueue_you_from_group', 'grouptool', $message)); } else { return array(false, get_string('unqueue_from_group', 'grouptool', $message)); } } else { $records = $DB->get_records('grouptool_queued', array('agrpid' => $agrpid, 'userid' => $userid)); $DB->delete_records('grouptool_queued', array('agrpid' => $agrpid, 'userid' => $userid)); foreach ($records as $cur) { // Trigger the Event! $cur->groupid = $groupdata->id; \mod_grouptool\event\queue_entry_deleted::create_direct($this->cm, $cur)->trigger(); } if ($userid == $USER->id) { return array(false, get_string('unqueue_you_from_group_success', 'grouptool', $message)); } else { return array(false, get_string('unqueue_from_group_success', 'grouptool', $message)); } } } else { if ($userid == $USER->id) { return array(true, get_string('you_are_not_in_queue_or_registered', 'grouptool', $message)); } else { return array(true, get_string('not_in_queue_or_registered', 'grouptool', $message)); } } } } else { return array(true, get_string('error_getting_data', 'grouptool')); } }
/** * Sends an email to each owner * * @param object $obj user array with courses attached * @return array of courses that match the search */ protected function sendemail($obj) { global $CFG, $DB; if (empty($CFG->siteadmins)) { // Should not happen on an ordinary site. return false; } else { $admin = get_admin(); } $config = get_config('tool_coursearchiver'); switch ($this->mode) { case self::MODE_HIDEEMAIL: $subject = get_string('hidewarningsubject', 'tool_coursearchiver'); $message = $config->hidewarningemailsetting; break; case self::MODE_ARCHIVEEMAIL: $subject = get_string('archivewarningsubject', 'tool_coursearchiver'); $message = $config->archivewarningemailsetting; break; default: $this->errors[] = get_string('invalidmode', 'tool_coursearchiver'); return false; } $courses = $this->get_email_courses($obj, $admin); if (!empty($courses)) { $c = ""; foreach ($courses as $coursetext) { $c .= $coursetext; } // Make sure both the %to variable and the %courses variable exist in the message template. if (!strstr($message, '%to')) { $this->errors[] = get_string('errormissingto', 'tool_coursearchiver'); return 0; } if (!strstr($message, '%courses')) { $this->errors[] = get_string('errormissingcourses', 'tool_coursearchiver'); return 0; } $vars = array('%to' => $obj["user"]->firstname . ' ' . $obj["user"]->lastname, '%courses' => $c); $message = strtr(nl2br($message), $vars); $event = new \core\message\message(); $event->component = 'tool_coursearchiver'; $event->name = 'courseowner'; $event->userfrom = core_user::get_noreply_user(); $event->userto = $obj["user"]; $event->subject = $subject; $event->fullmessage = ''; $event->fullmessageformat = FORMAT_MARKDOWN; $event->fullmessagehtml = $message; $event->smallmessage = $subject; $event->notification = '1'; $event->contexturl = $CFG->wwwroot; $event->contexturlname = 'Course Archiver'; $event->replyto = $admin->email; try { $messageid = message_send($event); } catch (Exception $e) { $this->errors[] = get_string('errorsendingemail', 'tool_coursearchiver', $obj["user"]); return false; } return count($courses); } else { return 0; } }
function send_mail($values, $error, $user, $asistentes, $eventname) { global $USER; $userfrom = core_user::get_noreply_user(); $userfrom->maildisplay = true; $message = get_string('dear', 'local_reservasalas') . $USER->firstname . ' ' . $USER->lastname . ': '; $message .= '<br></br>'; $message .= '<br></br>'; $message .= get_string('bookinginformation', 'local_reservasalas'); $message .= '<br></br>'; $message .= '<br></br>'; $message .= get_string('site', 'local_reservasalas') . ': ' . $campusId->nombre; $message .= '<br></br>'; $message .= get_string('buildings', 'local_reservasalas') . ': ' . $buildingId->nombre; $message .= '<br></br>'; $message .= get_string('roomtype', 'local_reservasalas') . ': Estudio'; $message .= '<br></br>'; $message .= get_string('event', 'local_reservasalas') . ': ' . $eventname; $message .= '<br></br>'; $message .= get_string('assistants', 'local_reservasalas') . ': ' . $asistentes; $message .= '<br></br>'; $message .= get_string('responsibility', 'local_reservasalas') . ': ' . $USER->firstname . ' ' . $USER->lastname; $message .= '<br></br>'; $message .= get_string('rooms', 'local_reservasalas') . ': '; $message .= '<br></br>'; foreach ($values as $value) { $message .= get_string('date', 'local_reservasalas') . ': ' . date("Y-m-d", $value["fecha"]) . ' - ' . get_string('room', 'local_reservasalas') . ': ' . $value['nombresala'] . ' - ' . get_string('module', 'local_reservasalas') . ': ' . $value['nombremodulo']; $message .= '<br></br>'; } $eventdata = new stdClass(); $eventdata->component = 'local_reservasalas'; // your component name $eventdata->name = 'reservenotification'; // this is the message name from messages.php $eventdata->userfrom = $userfrom; $eventdata->userto = $user; $eventdata->subject = get_string('confirmationbooking', 'local_reservasalas'); $eventdata->fullmessage = format_text_email($message, FORMAT_HTML); $eventdata->fullmessageformat = FORMAT_HTML; $eventdata->fullmessagehtml = ''; $eventdata->smallmessage = ''; $eventdata->notification = 1; // this is only set to 0 for personal messages between users message_send($eventdata); }
/** * Get the "from" contact which the email will be sent from. * * @param int $sendoption send email from constant ENROL_SEND_EMAIL_FROM_* * @param $context context where the user will be fetched * @return mixed|stdClass the contact user object. */ public function get_welcome_email_contact($sendoption, $context) { global $CFG; $contact = null; // Send as the first user assigned as the course contact. if ($sendoption == ENROL_SEND_EMAIL_FROM_COURSE_CONTACT) { $rusers = array(); if (!empty($CFG->coursecontact)) { $croles = explode(',', $CFG->coursecontact); list($sort, $sortparams) = users_order_by_sql('u'); // We only use the first user. $i = 0; do { $rusers = get_role_users($croles[$i], $context, true, '', 'r.sortorder ASC, ' . $sort, null, '', '', '', '', $sortparams); $i++; } while (empty($rusers) && !empty($croles[$i])); } if ($rusers) { $contact = array_values($rusers)[0]; } } else { if ($sendoption == ENROL_SEND_EMAIL_FROM_KEY_HOLDER) { // Send as the first user with enrol/self:holdkey capability assigned in the course. list($sort) = users_order_by_sql('u'); $keyholders = get_users_by_capability($context, 'enrol/self:holdkey', 'u.*', $sort); if (!empty($keyholders)) { $contact = array_values($keyholders)[0]; } } } // If send welcome email option is set to no reply or if none of the previous options have // returned a contact send welcome message as noreplyuser. if ($sendoption == ENROL_SEND_EMAIL_FROM_NOREPLY || empty($contact)) { $contact = core_user::get_noreply_user(); } return $contact; }
/** * Print the results of a message search * * @param mixed $frm submitted form data * @param bool $showicontext show text next to action icons? * @param object $currentuser the current user * @return void */ function message_print_search_results($frm, $showicontext = false, $currentuser = null) { global $USER, $DB, $OUTPUT; if (empty($currentuser)) { $currentuser = $USER; } echo html_writer::start_tag('div', array('class' => 'mdl-left')); $personsearch = false; $personsearchstring = null; if (!empty($frm->personsubmit) and !empty($frm->name)) { $personsearch = true; $personsearchstring = $frm->name; } else { if (!empty($frm->combinedsubmit) and !empty($frm->combinedsearch)) { $personsearch = true; $personsearchstring = $frm->combinedsearch; } } // Search for person. if ($personsearch) { if (optional_param('mycourses', 0, PARAM_BOOL)) { $users = array(); $mycourses = enrol_get_my_courses('id'); $mycoursesids = array(); foreach ($mycourses as $mycourse) { $mycoursesids[] = $mycourse->id; } $susers = message_search_users($mycoursesids, $personsearchstring); foreach ($susers as $suser) { $users[$suser->id] = $suser; } } else { $users = message_search_users(SITEID, $personsearchstring); } if (!empty($users)) { echo html_writer::start_tag('p', array('class' => 'heading searchresultcount')); echo get_string('userssearchresults', 'message', count($users)); echo html_writer::end_tag('p'); echo html_writer::start_tag('table', array('class' => 'messagesearchresults')); foreach ($users as $user) { if ($user->contactlistid) { if ($user->blocked == 0) { // User is not blocked. $strcontact = message_contact_link($user->id, 'remove', true, null, $showicontext); $strblock = message_contact_link($user->id, 'block', true, null, $showicontext); } else { // blocked $strcontact = message_contact_link($user->id, 'add', true, null, $showicontext); $strblock = message_contact_link($user->id, 'unblock', true, null, $showicontext); } } else { $strcontact = message_contact_link($user->id, 'add', true, null, $showicontext); $strblock = message_contact_link($user->id, 'block', true, null, $showicontext); } // Should we show just the icon or icon and text? $histicontext = 'icon'; if ($showicontext) { $histicontext = 'both'; } $strhistory = message_history_link($USER->id, $user->id, true, '', '', $histicontext); echo html_writer::start_tag('tr'); echo html_writer::start_tag('td', array('class' => 'pix')); echo $OUTPUT->user_picture($user, array('size' => 20, 'courseid' => SITEID)); echo html_writer::end_tag('td'); echo html_writer::start_tag('td', array('class' => 'contact')); $action = null; $link = new moodle_url("/message/index.php?id={$user->id}"); echo $OUTPUT->action_link($link, fullname($user), $action, array('title' => get_string('sendmessageto', 'message', fullname($user)))); echo html_writer::end_tag('td'); echo html_writer::tag('td', $strcontact, array('class' => 'link')); echo html_writer::tag('td', $strblock, array('class' => 'link')); echo html_writer::tag('td', $strhistory, array('class' => 'link')); echo html_writer::end_tag('tr'); } echo html_writer::end_tag('table'); } else { echo html_writer::start_tag('p', array('class' => 'heading searchresultcount')); echo get_string('userssearchresults', 'message', 0) . '<br /><br />'; echo html_writer::end_tag('p'); } } // search messages for keywords $messagesearch = false; $messagesearchstring = null; if (!empty($frm->keywords)) { $messagesearch = true; $messagesearchstring = clean_text(trim($frm->keywords)); } else { if (!empty($frm->combinedsubmit) and !empty($frm->combinedsearch)) { $messagesearch = true; $messagesearchstring = clean_text(trim($frm->combinedsearch)); } } if ($messagesearch) { if ($messagesearchstring) { $keywords = explode(' ', $messagesearchstring); } else { $keywords = array(); } $tome = false; $fromme = false; $courseid = 'none'; if (empty($frm->keywordsoption)) { $frm->keywordsoption = 'allmine'; } switch ($frm->keywordsoption) { case 'tome': $tome = true; break; case 'fromme': $fromme = true; break; case 'allmine': $tome = true; $fromme = true; break; case 'allusers': $courseid = SITEID; break; case 'courseusers': $courseid = $frm->courseid; break; default: $tome = true; $fromme = true; } if (($messages = message_search($keywords, $fromme, $tome, $courseid)) !== false) { // Get a list of contacts. if (($contacts = $DB->get_records('message_contacts', array('userid' => $USER->id), '', 'contactid, blocked')) === false) { $contacts = array(); } // Print heading with number of results. echo html_writer::start_tag('p', array('class' => 'heading searchresultcount')); $countresults = count($messages); if ($countresults == MESSAGE_SEARCH_MAX_RESULTS) { echo get_string('keywordssearchresultstoomany', 'message', $countresults) . ' ("' . s($messagesearchstring) . '")'; } else { echo get_string('keywordssearchresults', 'message', $countresults); } echo html_writer::end_tag('p'); // Print table headings. echo html_writer::start_tag('table', array('class' => 'messagesearchresults', 'cellspacing' => '0')); $headertdstart = html_writer::start_tag('td', array('class' => 'messagesearchresultscol')); $headertdend = html_writer::end_tag('td'); echo html_writer::start_tag('tr'); echo $headertdstart . get_string('from') . $headertdend; echo $headertdstart . get_string('to') . $headertdend; echo $headertdstart . get_string('message', 'message') . $headertdend; echo $headertdstart . get_string('timesent', 'message') . $headertdend; echo html_writer::end_tag('tr'); $blockedcount = 0; $dateformat = get_string('strftimedatetimeshort'); $strcontext = get_string('context', 'message'); foreach ($messages as $message) { // Ignore messages to and from blocked users unless $frm->includeblocked is set. if (!optional_param('includeblocked', 0, PARAM_BOOL) and (isset($contacts[$message->useridfrom]) and $contacts[$message->useridfrom]->blocked == 1 or isset($contacts[$message->useridto]) and $contacts[$message->useridto]->blocked == 1)) { $blockedcount++; continue; } // Load user-to record. if ($message->useridto !== $USER->id) { $userto = core_user::get_user($message->useridto); if ($userto === false) { $userto = core_user::get_noreply_user(); } $tocontact = (array_key_exists($message->useridto, $contacts) and $contacts[$message->useridto]->blocked == 0); $toblocked = (array_key_exists($message->useridto, $contacts) and $contacts[$message->useridto]->blocked == 1); } else { $userto = false; $tocontact = false; $toblocked = false; } // Load user-from record. if ($message->useridfrom !== $USER->id) { $userfrom = core_user::get_user($message->useridfrom); if ($userfrom === false) { $userfrom = core_user::get_noreply_user(); } $fromcontact = (array_key_exists($message->useridfrom, $contacts) and $contacts[$message->useridfrom]->blocked == 0); $fromblocked = (array_key_exists($message->useridfrom, $contacts) and $contacts[$message->useridfrom]->blocked == 1); } else { $userfrom = false; $fromcontact = false; $fromblocked = false; } // Find date string for this message. $date = usergetdate($message->timecreated); $datestring = $date['year'] . $date['mon'] . $date['mday']; // Print out message row. echo html_writer::start_tag('tr', array('valign' => 'top')); echo html_writer::start_tag('td', array('class' => 'contact')); message_print_user($userfrom, $fromcontact, $fromblocked, $showicontext); echo html_writer::end_tag('td'); echo html_writer::start_tag('td', array('class' => 'contact')); message_print_user($userto, $tocontact, $toblocked, $showicontext); echo html_writer::end_tag('td'); echo html_writer::start_tag('td', array('class' => 'summary')); echo message_get_fragment($message->smallmessage, $keywords); echo html_writer::start_tag('div', array('class' => 'link')); // If the user clicks the context link display message sender on the left. // EXCEPT if the current user is in the conversation. Current user == always on the left. $leftsideuserid = $rightsideuserid = null; if ($currentuser->id == $message->useridto) { $leftsideuserid = $message->useridto; $rightsideuserid = $message->useridfrom; } else { $leftsideuserid = $message->useridfrom; $rightsideuserid = $message->useridto; } message_history_link($leftsideuserid, $rightsideuserid, false, $messagesearchstring, 'm' . $message->id, $strcontext); echo html_writer::end_tag('div'); echo html_writer::end_tag('td'); echo html_writer::tag('td', userdate($message->timecreated, $dateformat), array('class' => 'date')); echo html_writer::end_tag('tr'); } if ($blockedcount > 0) { echo html_writer::start_tag('tr'); echo html_writer::tag('td', get_string('blockedmessages', 'message', $blockedcount), array('colspan' => 4, 'align' => 'center')); echo html_writer::end_tag('tr'); } echo html_writer::end_tag('table'); } else { echo html_writer::tag('p', get_string('keywordssearchresults', 'message', 0), array('class' => 'heading')); } } if (!$personsearch && !$messagesearch) { //they didn't enter any search terms echo $OUTPUT->notification(get_string('emptysearchstring', 'message')); } echo html_writer::end_tag('div'); }
/** * group_remove_member_handler * event: groups_member_removed * schedule: instant * * @param \core\event\group_member_removed $event Event object containing useful data * @return bool true if success */ public static function group_member_removed(\core\event\group_member_removed $event) { global $DB, $CFG; $sql = "SELECT DISTINCT {grouptool}.id, {grouptool}.ifmemberremoved, {grouptool}.course,\n {grouptool}.use_queue, {grouptool}.immediate_reg, {grouptool}.allow_multiple,\n {grouptool}.choose_max, {grouptool}.name\n FROM {grouptool}\n RIGHT JOIN {grouptool_agrps} agrp ON agrp.grouptoolid = {grouptool}.id\n WHERE agrp.groupid = ?"; $params = array($event->objectid); if (!($grouptools = $DB->get_records_sql($sql, $params))) { return true; } $sql = "SELECT agrps.grouptoolid grouptoolid, agrps.id id\n FROM {grouptool_agrps} agrps\n WHERE agrps.groupid = :groupid"; $agrp = $DB->get_records_sql($sql, array('groupid' => $event->objectid)); foreach ($grouptools as $grouptool) { switch ($grouptool->ifmemberremoved) { case GROUPTOOL_FOLLOW: $sql = "SELECT reg.id AS id, reg.agrpid AS agrpid, reg.userid AS userid, agrps.groupid\n FROM {grouptool_agrps} agrps\n INNER JOIN {grouptool_registered} reg ON agrps.id = reg.agrpid\n WHERE reg.userid = :userid\n AND agrps.grouptoolid = :grouptoolid\n AND agrps.groupid = :groupid"; if ($regs = $DB->get_records_sql($sql, array('grouptoolid' => $grouptool->id, 'userid' => $event->relateduserid, 'groupid' => $event->objectid))) { $DB->delete_records_list('grouptool_registered', 'id', array_keys($regs)); foreach ($regs as $reg) { // Trigger event! $cm = get_coursemodule_from_instance('grouptool', $grouptool->id, $grouptool->course, false, MUST_EXIST); \mod_grouptool\event\registration_deleted::create_via_eventhandler($cm, $reg)->trigger(); } // Get next queued user and put him in the group (and delete queue entry)! if (!empty($grouptool->use_queue)) { $agrpids = $DB->get_fieldset_sql('SELECT id FROM {grouptool_agrps} WHERE grouptoolid = ?', array($grouptool->id)); list($agrpssql, $agrpsparam) = $DB->get_in_or_equal($agrpids); $sql = "SELECT queued.id, MAX(queued.agrpid) AS agrpid, MAX(queued.userid) AS userid,\n MAX(queued.timestamp), (COUNT(DISTINCT reg.id) < ?) AS priority\n FROM {grouptool_queued} queued\n LEFT JOIN {grouptool_registered} reg ON queued.userid = reg.userid\n AND reg.agrpid " . $agrpssql . "\n WHERE queued.agrpid = ?\n GROUP BY queued.id\n ORDER BY priority DESC, queued.timestamp ASC\n LIMIT 1"; $params = array_merge(array($grouptool->choose_max), $agrpsparam, array($agrp[$grouptool->id]->id)); $record = $DB->get_record_sql($sql, $params); if (is_object($record)) { $newrecord = clone $record; unset($newrecord->id); $newrecord->modified_by = $newrecord->userid; $newrecord->id = $DB->insert_record('grouptool_registered', $newrecord); if (!empty($grouptool->immediate_reg)) { groups_add_member($event->objectid, $newrecord->userid); } // Trigger event! // We got the cm above already! $newrecord->groupid = $event->objectid; $record->groupid = $event->objectid; \mod_grouptool\event\user_moved::promotion_from_queue($cm, $record, $newrecord)->trigger(); $allowm = $grouptool->allow_multiple; $agrps = $DB->get_fieldset_sql("SELECT id\n FROM {grouptool_agrps} agrps\n WHERE agrps.grouptoolid = :grptlid", array('grptlid' => $grouptool->id)); list($sql, $params) = $DB->get_in_or_equal($agrps); $usrregcnt = $DB->count_records_select('grouptool_registered', ' userid = ? AND agrpid ' . $sql, array_merge(array($newrecord->userid), $params)); $max = $grouptool->choose_max; // Get belonging course! $course = $DB->get_record('course', array('id' => $grouptool->course)); // Get CM! $cm = get_coursemodule_from_instance('grouptool', $grouptool->id, $course->id); $message = new stdClass(); $userdata = $DB->get_record('user', array('id' => $newrecord->userid)); $message->username = fullname($userdata); $groupdata = $DB->get_record('grouptool_agrps', array('id' => $agrp[$grouptool->id]->id)); $groupdata->name = $DB->get_field('groups', 'name', array('id' => $groupdata->groupid)); $message->groupname = $groupdata->name; $strgrouptools = get_string("modulenameplural", "grouptool"); $strgrouptool = get_string("modulename", "grouptool"); $postsubject = $course->shortname . ': ' . $strgrouptools . ': ' . format_string($grouptool->name, true); $posttext = $course->shortname . ' -> ' . $strgrouptools . ' -> ' . format_string($grouptool->name, true) . "\n"; $posttext .= "----------------------------------------------------------\n"; $posttext .= get_string("register_you_in_group_successmail", "grouptool", $message) . "\n"; $posttext .= "----------------------------------------------------------\n"; $usermailformat = $DB->get_field('user', 'mailformat', array('id' => $newrecord->userid)); if ($usermailformat == 1) { // HTML! $posthtml = "<p><font face=\"sans-serif\">"; $posthtml = "<a href=\"" . $CFG->wwwroot . "/course/view.php?id=" . $course->id . "\">" . $course->shortname . "</a> ->"; $posthtml = "<a href=\"" . $CFG->wwwroot . "/mod/grouptool/index.php?id=" . $course->id . "\">" . $strgrouptools . "</a> ->"; $posthtml = "<a href=\"" . $CFG->wwwroot . "/mod/grouptool/view.php?id=" . $cm->id . "\">" . format_string($grouptool->name, true) . "</a></font></p>"; $posthtml .= "<hr /><font face=\"sans-serif\">"; $posthtml .= "<p>" . get_string("register_you_in_group_successmailhtml", "grouptool", $message) . "</p>"; $posthtml .= "</font><hr />"; } else { $posthtml = ""; } $messageuser = $DB->get_record('user', array('id' => $newrecord->userid)); $eventdata = new stdClass(); $eventdata->modulename = 'grouptool'; $userfrom = core_user::get_noreply_user(); $eventdata->userfrom = $userfrom; $eventdata->userto = $messageuser; $eventdata->subject = $postsubject; $eventdata->fullmessage = $posttext; $eventdata->fullmessageformat = FORMAT_PLAIN; $eventdata->fullmessagehtml = $posthtml; $eventdata->smallmessage = get_string('register_you_in_group_success', 'grouptool', $message); $eventdata->name = 'grouptool_moveupreg'; $eventdata->component = 'mod_grouptool'; $eventdata->notification = 1; $eventdata->contexturl = $CFG->wwwroot . '/mod/grouptool/view.php?id=' . $cm->id; $eventdata->contexturlname = $grouptool->name; message_send($eventdata); if ($allowm && $usrregcnt >= $max || !$allowm) { // Get all queue entries and trigger queue_entry_deleted events for each! $queueentries = $DB->get_records_sql("SELECT queued.*, agrp.groupid\n FROM {grouptool_queued} queued\n JOIN {grouptool_agrps} agrp ON queued.agrpid = agrp.id\n WHERE userid = ? AND agrpid " . $sql, array_merge(array($newrecord->userid), $params)); $DB->delete_records_select('grouptool_queued', ' userid = ? AND agrpid ' . $sql, array_merge(array($newrecord->userid), $params)); foreach ($queueentries as $cur) { // Trigger event! // We got the cm above already! \mod_grouptool\event\queue_entry_deleted::create_via_eventhandler($cm, $cur)->trigger(); } } else { $queueentries = $DB->get_records_sql("SELECT queued.*, agrp.groupid\n FROM {grouptool_queued} queued\n JOIN {grouptool_agrps} agrp ON queued.agrpid = agrp.id\n WHERE userid = :userid AND agrpid = :agrpid", array('userid' => $newrecord->userid, 'agrpid' => $agrp[$grouptool->id]->id)); $DB->delete_records('grouptool_queued', array('userid' => $newrecord->userid, 'agrpid' => $agrp[$grouptool->id]->id)); foreach ($queueentries as $cur) { // Trigger event! // We got the cm above already! \mod_grouptool\event\queue_entry_deleted::create_via_eventhandler($cm, $cur)->trigger(); } } } } } break; default: case GROUPTOOL_IGNORE: break; } } return true; }
// Trigger event. \core\event\user_updated::create_from_userid($user->id)->trigger(); // If email was changed and confirmation is required, send confirmation email now to the new address. if ($emailchanged && $CFG->emailchangeconfirmation) { $tempuser = $DB->get_record('user', array('id' => $user->id), '*', MUST_EXIST); $tempuser->email = $usernew->preference_newemail; $supportuser = core_user::get_support_user(); $a = new stdClass(); $a->url = $CFG->wwwroot . '/user/emailupdate.php?key=' . $usernew->preference_newemailkey . '&id=' . $user->id; $a->site = format_string($SITE->fullname, true, array('context' => context_course::instance(SITEID))); $a->fullname = fullname($tempuser, true); $a->supportemail = $supportuser->email; $emailupdatemessage = get_string('emailupdatemessage', 'auth', $a); $emailupdatetitle = get_string('emailupdatetitle', 'auth', $a); // Email confirmation directly rather than using messaging so they will definitely get an email. $noreplyuser = core_user::get_noreply_user(); if (!($mailresults = email_to_user($tempuser, $noreplyuser, $emailupdatetitle, $emailupdatemessage))) { die("could not send email!"); } } // Reload from db, we need new full name on this page if we do not redirect. $user = $DB->get_record('user', array('id' => $user->id), '*', MUST_EXIST); if ($USER->id == $user->id) { // Override old $USER session variable if needed. foreach ((array) $user as $variable => $value) { if ($variable === 'description' or $variable === 'password') { // These are not set for security nad perf reasons. continue; } $USER->{$variable} = $value; }
function reservasalas_sendMail($values, $error, $user, $asistentes, $eventname, $buildingid) { global $USER, $DB; $userfrom = core_user::get_noreply_user(); $userfrom->maildisplay = true; $sql = "SELECT s.nombre as sedenombre, e.nombre as edificionombre\n\t\t\tFROM {reservasalas_edificios} AS e JOIN {reservasalas_sedes} AS s ON (e.sedes_id = s.id)\n\t\t\tWHERE s.id = ?"; $names = $DB->get_record_sql($sql, array($buildingid)); $message = get_string("dear", "local_reservasalas") . $USER->firstname . " " . $USER->lastname . ": \n \n"; $message .= get_string("bookinginformation", "local_reservasalas") . "\n \n"; $message .= get_string("site", "local_reservasalas") . ": " . $names->sedenombre . "\n"; $message .= get_string("buildings", "local_reservasalas") . ": " . $names->edificionombre . "\n"; $message .= get_string("roomtype", "local_reservasalas") . ": Estudio \n"; $message .= get_string("event", "local_reservasalas") . ": " . $eventname . "\n"; $message .= get_string("assistants", "local_reservasalas") . ": " . $asistentes . "\n"; $message .= get_string("responsibility", "local_reservasalas") . ": " . $USER->firstname . " " . $USER->lastname . "\n"; $message .= get_string("rooms", "local_reservasalas") . ": \n"; foreach ($values as $value) { $stamp = strtotime($value["fecha"]); $day = date("l", $stamp); $message .= get_string("date", "local_reservasalas") . ": " . $day . " " . $value["fecha"] . " - " . get_string("room", "local_reservasalas") . ": " . $value["nombresala"] . " - " . get_string("module", "local_reservasalas") . ": " . $value["nombremodulo"] . "\n"; } // Format each "\n" into a line break $formattedMessage = nl2br($message); $eventdata = new stdClass(); $eventdata->component = "local_reservasalas"; // your component name $eventdata->name = "reservenotification"; // this is the message name from messages.php $eventdata->userfrom = $userfrom; $eventdata->userto = $user; $eventdata->subject = get_string("confirmationbooking", "local_reservasalas"); $eventdata->fullmessage = format_text_email($formattedMessage, FORMAT_HTML); $eventdata->fullmessageformat = FORMAT_HTML; $eventdata->fullmessagehtml = ""; $eventdata->smallmessage = ""; $eventdata->notification = 1; // this is only set to 0 for personal messages between users message_send($eventdata); }
/** * Send the notification message when a quiz attempt becomes overdue. * * @param quiz_attempt $attemptobj all the data about the quiz attempt. */ function quiz_send_overdue_message($attemptobj) { global $CFG, $DB; $submitter = $DB->get_record('user', array('id' => $attemptobj->get_userid()), '*', MUST_EXIST); if (!$attemptobj->has_capability('mod/quiz:emailwarnoverdue', $submitter->id, false)) { return; // Message not required. } if (!$attemptobj->has_response_to_at_least_one_graded_question()) { return; // Message not required. } // Prepare lots of useful information that admins might want to include in // the email message. $quizname = format_string($attemptobj->get_quiz_name()); $deadlines = array(); if ($attemptobj->get_quiz()->timelimit) { $deadlines[] = $attemptobj->get_attempt()->timestart + $attemptobj->get_quiz()->timelimit; } if ($attemptobj->get_quiz()->timeclose) { $deadlines[] = $attemptobj->get_quiz()->timeclose; } $duedate = min($deadlines); $graceend = $duedate + $attemptobj->get_quiz()->graceperiod; $a = new stdClass(); // Course info. $a->coursename = format_string($attemptobj->get_course()->fullname); $a->courseshortname = format_string($attemptobj->get_course()->shortname); // Quiz info. $a->quizname = $quizname; $a->quizurl = $attemptobj->view_url(); $a->quizlink = '<a href="' . $a->quizurl . '">' . $quizname . '</a>'; // Attempt info. $a->attemptduedate = userdate($duedate); $a->attemptgraceend = userdate($graceend); $a->attemptsummaryurl = $attemptobj->summary_url()->out(false); $a->attemptsummarylink = '<a href="' . $a->attemptsummaryurl . '">' . $quizname . ' review</a>'; // Student's info. $a->studentidnumber = $submitter->idnumber; $a->studentname = fullname($submitter); $a->studentusername = $submitter->username; // Prepare the message. $eventdata = new stdClass(); $eventdata->component = 'mod_quiz'; $eventdata->name = 'attempt_overdue'; $eventdata->notification = 1; $eventdata->userfrom = core_user::get_noreply_user(); $eventdata->userto = $submitter; $eventdata->subject = get_string('emailoverduesubject', 'quiz', $a); $eventdata->fullmessage = get_string('emailoverduebody', 'quiz', $a); $eventdata->fullmessageformat = FORMAT_PLAIN; $eventdata->fullmessagehtml = ''; $eventdata->smallmessage = get_string('emailoverduesmall', 'quiz', $a); $eventdata->contexturl = $a->quizurl; $eventdata->contexturlname = $a->quizname; // Send the message. return message_send($eventdata); }
function send_mail($values, $error, $user, $asistentes, $eventname, $campusId) { global $USER, $DB; $userfrom = core_user::get_noreply_user(); $userfrom->maildisplay = true; $sql = "SELECT e.nombre AS edificio, \n\t\t\ts.nombre AS sede\n\t\t\tFROM {reservasalas_edificios} AS e, \n\t\t\t{reservasalas_sedes} AS s \n\t\t\tWHERE e.sedes_id=s.id\n\t\t\tAND e.id=?"; $campus = $DB->get_record_sql($sql, array($campusId)); $message = get_string('dear', 'local_reservasalas') . $USER->firstname . ' ' . $USER->lastname . ': '; $message .= '<br></br>'; $message .= '<br></br>'; $message .= get_string('bookinginformation', 'local_reservasalas'); $message .= '<br></br>'; $message .= '<br></br>'; $message .= get_string('site', 'local_reservasalas') . ': ' . $campus->sede; $message .= '<br></br>'; $message .= get_string('buildings', 'local_reservasalas') . ': ' . $campus->edificio; $message .= '<br></br>'; $message .= get_string('roomtype', 'local_reservasalas') . ': Estudio'; $message .= '<br></br>'; $message .= get_string('event', 'local_reservasalas') . ': ' . $eventname; $message .= '<br></br>'; $message .= get_string('assistants', 'local_reservasalas') . ': ' . $asistentes; $message .= '<br></br>'; $message .= get_string('responsibility', 'local_reservasalas') . ': ' . $USER->firstname . ' ' . $USER->lastname; $message .= '<br></br>'; $message .= get_string('rooms', 'local_reservasalas') . ': '; $message .= '<br></br>'; foreach ($values as $value) { $stamp = strtotime($value["fecha"]); $day = date("l", $stamp); $message .= get_string('date', 'local_reservasalas') . ': ' . $day . ' ' . $value["fecha"] . ' - ' . get_string('room', 'local_reservasalas') . ': ' . $value['nombresala'] . ' - ' . get_string('module', 'local_reservasalas') . ': ' . $value['nombremodulo']; $message .= '<br></br>'; } $eventdata = new stdClass(); $eventdata->component = 'local_reservasalas'; // your component name $eventdata->name = 'reservenotification'; // this is the message name from messages.php $eventdata->userfrom = $userfrom; $eventdata->userto = $user; $eventdata->subject = get_string('confirmationbooking', 'local_reservasalas'); $eventdata->fullmessage = format_text_email($message, FORMAT_HTML); $eventdata->fullmessageformat = FORMAT_HTML; $eventdata->fullmessagehtml = ''; $eventdata->smallmessage = ''; $eventdata->notification = 1; // this is only set to 0 for personal messages between users message_send($eventdata); }
/** * Sends notifications to users about awarded badges. * * @param badge $badge Badge that was issued * @param int $userid Recipient ID * @param string $issued Unique hash of an issued badge * @param string $filepathhash File path hash of an issued badge for attachments */ function badges_notify_badge_award(badge $badge, $userid, $issued, $filepathhash) { global $CFG, $DB; $admin = get_admin(); $userfrom = new stdClass(); $userfrom->id = $admin->id; $userfrom->email = !empty($CFG->badges_defaultissuercontact) ? $CFG->badges_defaultissuercontact : $admin->email; foreach (get_all_user_name_fields() as $addname) { $userfrom->{$addname} = !empty($CFG->badges_defaultissuername) ? '' : $admin->{$addname}; } $userfrom->firstname = !empty($CFG->badges_defaultissuername) ? $CFG->badges_defaultissuername : $admin->firstname; $userfrom->maildisplay = true; $issuedlink = html_writer::link(new moodle_url('/badges/badge.php', array('hash' => $issued)), $badge->name); $userto = $DB->get_record('user', array('id' => $userid), '*', MUST_EXIST); $params = new stdClass(); $params->badgename = $badge->name; $params->username = fullname($userto); $params->badgelink = $issuedlink; $message = badge_message_from_template($badge->message, $params); $plaintext = html_to_text($message); // Notify recipient. $eventdata = new stdClass(); $eventdata->component = 'moodle'; $eventdata->name = 'badgerecipientnotice'; $eventdata->userfrom = $userfrom; $eventdata->userto = $userto; $eventdata->notification = 1; $eventdata->subject = $badge->messagesubject; $eventdata->fullmessage = $plaintext; $eventdata->fullmessageformat = FORMAT_HTML; $eventdata->fullmessagehtml = $message; $eventdata->smallmessage = ''; // Attach badge image if possible. if (!empty($CFG->allowattachments) && $badge->attachment && is_string($filepathhash)) { $fs = get_file_storage(); $file = $fs->get_file_by_hash($filepathhash); $eventdata->attachment = $file; $eventdata->attachname = str_replace(' ', '_', $badge->name) . ".png"; message_send($eventdata); } else { message_send($eventdata); } // Notify badge creator about the award if they receive notifications every time. if ($badge->notification == 1) { $userfrom = core_user::get_noreply_user(); $userfrom->maildisplay = true; $creator = $DB->get_record('user', array('id' => $badge->usercreated), '*', MUST_EXIST); $a = new stdClass(); $a->user = fullname($userto); $a->link = $issuedlink; $creatormessage = get_string('creatorbody', 'badges', $a); $creatorsubject = get_string('creatorsubject', 'badges', $badge->name); $eventdata = new stdClass(); $eventdata->component = 'moodle'; $eventdata->name = 'badgecreatornotice'; $eventdata->userfrom = $userfrom; $eventdata->userto = $creator; $eventdata->notification = 1; $eventdata->subject = $creatorsubject; $eventdata->fullmessage = html_to_text($creatormessage); $eventdata->fullmessageformat = FORMAT_HTML; $eventdata->fullmessagehtml = $creatormessage; $eventdata->smallmessage = ''; message_send($eventdata); $DB->set_field('badge_issued', 'issuernotified', time(), array('badgeid' => $badge->id, 'userid' => $userid)); } }
/** * Retrieve $user1's contacts (online, offline and strangers) * * @param object $user1 the user whose messages are being viewed * @param object $user2 the user $user1 is talking to. If they are a contact * they will have a variable called 'iscontact' added to their user object * @return array containing 3 arrays. array($onlinecontacts, $offlinecontacts, $strangers) */ function message_get_contacts($user1=null, $user2=null) { global $DB, $CFG, $USER; if (empty($user1)) { $user1 = $USER; } if (!empty($user2)) { $user2->iscontact = false; } $timetoshowusers = 300; //Seconds default if (isset($CFG->block_online_users_timetosee)) { $timetoshowusers = $CFG->block_online_users_timetosee * 60; } // time which a user is counting as being active since $timefrom = time()-$timetoshowusers; // people in our contactlist who are online $onlinecontacts = array(); // people in our contactlist who are offline $offlinecontacts = array(); // people who are not in our contactlist but have sent us a message $strangers = array(); $userfields = user_picture::fields('u', array('lastaccess')); // get all in our contactlist who are not blocked in our contact list // and count messages we have waiting from each of them $contactsql = "SELECT $userfields, COUNT(m.id) AS messagecount FROM {message_contacts} mc JOIN {user} u ON u.id = mc.contactid LEFT OUTER JOIN {message} m ON m.useridfrom = mc.contactid AND m.useridto = ? WHERE u.deleted = 0 AND mc.userid = ? AND mc.blocked = 0 GROUP BY $userfields ORDER BY u.firstname ASC"; $rs = $DB->get_recordset_sql($contactsql, array($user1->id, $user1->id)); foreach ($rs as $rd) { if ($rd->lastaccess >= $timefrom) { // they have been active recently, so are counted online $onlinecontacts[] = $rd; } else { $offlinecontacts[] = $rd; } if (!empty($user2) && $user2->id == $rd->id) { $user2->iscontact = true; } } $rs->close(); // get messages from anyone who isn't in our contact list and count the number // of messages we have from each of them $strangersql = "SELECT $userfields, count(m.id) as messagecount FROM {message} m JOIN {user} u ON u.id = m.useridfrom LEFT OUTER JOIN {message_contacts} mc ON mc.contactid = m.useridfrom AND mc.userid = m.useridto WHERE u.deleted = 0 AND mc.id IS NULL AND m.useridto = ? GROUP BY $userfields ORDER BY u.firstname ASC"; $rs = $DB->get_recordset_sql($strangersql, array($USER->id)); // Add user id as array index, so supportuser and noreply user don't get duplicated (if they are real users). foreach ($rs as $rd) { $strangers[$rd->id] = $rd; } $rs->close(); // Add noreply user and support user to the list, if they don't exist. $supportuser = core_user::get_support_user(); if (!isset($strangers[$supportuser->id])) { $supportuser->messagecount = message_count_unread_messages($USER, $supportuser); if ($supportuser->messagecount > 0) { $strangers[$supportuser->id] = $supportuser; } } $noreplyuser = core_user::get_noreply_user(); if (!isset($strangers[$noreplyuser->id])) { $noreplyuser->messagecount = message_count_unread_messages($USER, $noreplyuser); if ($noreplyuser->messagecount > 0) { $strangers[$noreplyuser->id] = $noreplyuser; } } return array($onlinecontacts, $offlinecontacts, $strangers); }
/** * Do the job. * Throw exceptions on errors (the job will be retried). */ public function execute() { global $CFG, $DB; if (empty($CFG->notifyloginfailures)) { return; } $recip = get_users_from_config($CFG->notifyloginfailures, 'moodle/site:config'); // Do not look back more than 1 month to avoid crashes due to huge number of records. $maximumlastnotifytime = time() - self::NOTIFY_MAXIMUM_TIME; if (empty($CFG->lastnotifyfailure) || $CFG->lastnotifyfailure < $maximumlastnotifytime) { $CFG->lastnotifyfailure = $maximumlastnotifytime; } // If it has been less than an hour, or if there are no recipients, don't execute. if (time() - HOURSECS < $CFG->lastnotifyfailure || !is_array($recip) || count($recip) <= 0) { return; } // We need to deal with the threshold stuff first. if (empty($CFG->notifyloginthreshold)) { $CFG->notifyloginthreshold = 10; // Default to something sensible. } // Get all the IPs with more than notifyloginthreshold failures since lastnotifyfailure // and insert them into the cache_flags temp table. $logmang = get_log_manager(); $readers = $logmang->get_readers('\\core\\log\\sql_internal_table_reader'); $reader = reset($readers); $readername = key($readers); if (empty($reader) || empty($readername)) { // No readers, no processing. return true; } $logtable = $reader->get_internal_log_table_name(); $sql = "SELECT ip, COUNT(*)\n FROM {" . $logtable . "}\n WHERE eventname = ?\n AND timecreated > ?\n GROUP BY ip\n HAVING COUNT(*) >= ?"; $params = array('\\core\\event\\user_login_failed', $CFG->lastnotifyfailure, $CFG->notifyloginthreshold); $rs = $DB->get_recordset_sql($sql, $params); foreach ($rs as $iprec) { if (!empty($iprec->ip)) { set_cache_flag('login_failure_by_ip', $iprec->ip, '1', 0); } } $rs->close(); // Get all the INFOs with more than notifyloginthreshold failures since lastnotifyfailure // and insert them into the cache_flags temp table. $sql = "SELECT userid, count(*)\n FROM {" . $logtable . "}\n WHERE eventname = ?\n AND timecreated > ?\n GROUP BY userid\n HAVING count(*) >= ?"; $params = array('\\core\\event\\user_login_failed', $CFG->lastnotifyfailure, $CFG->notifyloginthreshold); $rs = $DB->get_recordset_sql($sql, $params); foreach ($rs as $inforec) { if (!empty($inforec->info)) { set_cache_flag('login_failure_by_id', $inforec->userid, '1', 0); } } $rs->close(); // Now, select all the login error logged records belonging to the ips and infos // since lastnotifyfailure, that we have stored in the cache_flags table. $namefields = get_all_user_name_fields(true, 'u'); $sql = "SELECT * FROM (\n SELECT l.*, u.username, {$namefields}\n FROM {" . $logtable . "} l\n JOIN {cache_flags} cf ON l.ip = cf.name\n LEFT JOIN {user} u ON l.userid = u.id\n WHERE l.eventname = ?\n AND l.timecreated > ?\n AND cf.flagtype = 'login_failure_by_ip'\n UNION ALL\n SELECT l.*, u.username, {$namefields}\n FROM {" . $logtable . "} l\n JOIN {cache_flags} cf ON l.userid = " . $DB->sql_cast_char2int('cf.name') . "\n LEFT JOIN {user} u ON l.userid = u.id\n WHERE l.eventname = ?\n AND l.timecreated > ?\n AND cf.flagtype = 'login_failure_by_info') t\n ORDER BY t.timecreated DESC"; $params = array('\\core\\event\\user_login_failed', $CFG->lastnotifyfailure, '\\core\\event\\user_login_failed', $CFG->lastnotifyfailure); // Init some variables. $count = 0; $messages = ''; // Iterate over the logs recordset. $rs = $DB->get_recordset_sql($sql, $params); foreach ($rs as $log) { $a = new \stdClass(); $a->time = userdate($log->timecreated); if (empty($log->username)) { // Entries with no valid username. We get attempted username from the event's other field. $other = unserialize($log->other); $a->info = empty($other['username']) ? '' : $other['username']; $a->name = get_string('unknownuser'); } else { $a->info = $log->username; $a->name = fullname($log); } $a->ip = $log->ip; $messages .= get_string('notifyloginfailuresmessage', '', $a) . "\n"; $count++; } $rs->close(); // If we have something useful to report. if ($count > 0) { $site = get_site(); $subject = get_string('notifyloginfailuressubject', '', format_string($site->fullname)); // Calculate the complete body of notification (start + messages + end). $params = array('id' => 0, 'modid' => 'site_errors', 'chooselog' => '1', 'logreader' => $readername); $url = new \moodle_url('/report/log/index.php', $params); $body = get_string('notifyloginfailuresmessagestart', '', $CFG->wwwroot) . ($CFG->lastnotifyfailure != 0 ? '(' . userdate($CFG->lastnotifyfailure) . ')' : '') . "\n\n" . $messages . "\n\n" . get_string('notifyloginfailuresmessageend', '', $url->out(false) . ' ') . "\n\n"; // For each destination, send mail. mtrace('Emailing admins about ' . $count . ' failed login attempts'); foreach ($recip as $admin) { // Emailing the admins directly rather than putting these through the messaging system. email_to_user($admin, \core_user::get_noreply_user(), $subject, $body); } } // Update lastnotifyfailure with current time. set_config('lastnotifyfailure', time()); // Finally, delete all the temp records we have created in cache_flags. $DB->delete_records_select('cache_flags', "flagtype IN ('login_failure_by_ip', 'login_failure_by_info')"); }
/** * Ensure that the noreply user is not cached. */ public function test_get_noreply_user() { global $CFG; // Create a new fake language 'xx' with the 'noreplyname'. $langfolder = $CFG->dataroot . '/lang/xx'; check_dir_exists($langfolder); $langconfig = "<?php\n\\defined('MOODLE_INTERNAL') || die();"; file_put_contents($langfolder . '/langconfig.php', $langconfig); $langconfig = "<?php\n\$string['noreplyname'] = 'XXX';"; file_put_contents($langfolder . '/moodle.php', $langconfig); $CFG->lang = 'en'; $enuser = \core_user::get_noreply_user(); $CFG->lang = 'xx'; $xxuser = \core_user::get_noreply_user(); $this->assertNotEquals($enuser, $xxuser); }
/** * Test get_messages. */ public function test_get_messages() { global $CFG; $this->resetAfterTest(true); $this->preventResetByRollback(); // This mark the messages as read!. $sink = $this->redirectMessages(); $user1 = self::getDataGenerator()->create_user(); $user2 = self::getDataGenerator()->create_user(); $user3 = self::getDataGenerator()->create_user(); $course = self::getDataGenerator()->create_course(); // Send a message from one user to another. message_post_message($user1, $user2, 'some random text 1', FORMAT_MOODLE); message_post_message($user1, $user3, 'some random text 2', FORMAT_MOODLE); message_post_message($user2, $user3, 'some random text 3', FORMAT_MOODLE); message_post_message($user3, $user2, 'some random text 4', FORMAT_MOODLE); message_post_message($user3, $user1, 'some random text 5', FORMAT_MOODLE); $this->setUser($user1); // Get read conversations from user1 to user2. $messages = core_message_external::get_messages($user2->id, $user1->id, 'conversations', true, true, 0, 0); $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); $this->assertCount(1, $messages['messages']); // Get unread conversations from user1 to user2. $messages = core_message_external::get_messages($user2->id, $user1->id, 'conversations', false, true, 0, 0); $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); $this->assertCount(0, $messages['messages']); // Get read messages send from user1. $messages = core_message_external::get_messages(0, $user1->id, 'conversations', true, true, 0, 0); $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); $this->assertCount(2, $messages['messages']); $this->setUser($user2); // Get read conversations from any user to user2. $messages = core_message_external::get_messages($user2->id, 0, 'conversations', true, true, 0, 0); $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); $this->assertCount(2, $messages['messages']); $this->setUser($user3); // Get read notifications received by user3. $messages = core_message_external::get_messages($user3->id, 0, 'notifications', true, true, 0, 0); $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); $this->assertCount(0, $messages['messages']); // Now, create some notifications... // We are creating fake notifications but based on real ones. // This one omits notification = 1. $eventdata = new stdClass(); $eventdata->modulename = 'moodle'; $eventdata->component = 'enrol_paypal'; $eventdata->name = 'paypal_enrolment'; $eventdata->userfrom = get_admin(); $eventdata->userto = $user1; $eventdata->subject = "Moodle: PayPal payment"; $eventdata->fullmessage = "Your PayPal payment is pending."; $eventdata->fullmessageformat = FORMAT_PLAIN; $eventdata->fullmessagehtml = ''; $eventdata->smallmessage = ''; message_send($eventdata); $message = new stdClass(); $message->notification = 1; $message->component = 'enrol_manual'; $message->name = 'expiry_notification'; $message->userfrom = $user2; $message->userto = $user1; $message->subject = 'Enrolment expired'; $message->fullmessage = 'Enrolment expired blah blah blah'; $message->fullmessageformat = FORMAT_MARKDOWN; $message->fullmessagehtml = markdown_to_html($message->fullmessage); $message->smallmessage = $message->subject; $message->contexturlname = $course->fullname; $message->contexturl = (string) new moodle_url('/course/view.php', array('id' => $course->id)); message_send($message); $userfrom = core_user::get_noreply_user(); $userfrom->maildisplay = true; $eventdata = new stdClass(); $eventdata->component = 'moodle'; $eventdata->name = 'badgecreatornotice'; $eventdata->userfrom = $userfrom; $eventdata->userto = $user1; $eventdata->notification = 1; $eventdata->subject = 'New badge'; $eventdata->fullmessage = format_text_email($eventdata->subject, FORMAT_HTML); $eventdata->fullmessageformat = FORMAT_PLAIN; $eventdata->fullmessagehtml = $eventdata->subject; $eventdata->smallmessage = $eventdata->subject; message_send($eventdata); $eventdata = new stdClass(); $eventdata->name = 'submission'; $eventdata->component = 'mod_feedback'; $eventdata->userfrom = $user1; $eventdata->userto = $user2; $eventdata->subject = 'Feedback submitted'; $eventdata->fullmessage = 'Feedback submitted from an user'; $eventdata->fullmessageformat = FORMAT_PLAIN; $eventdata->fullmessagehtml = '<strong>Feedback submitted</strong>'; $eventdata->smallmessage = ''; message_send($eventdata); $this->setUser($user1); // Get read notifications from any user to user1. $messages = core_message_external::get_messages($user1->id, 0, 'notifications', true, true, 0, 0); $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); $this->assertCount(3, $messages['messages']); // Get one read notifications from any user to user1. $messages = core_message_external::get_messages($user1->id, 0, 'notifications', true, true, 0, 1); $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); $this->assertCount(1, $messages['messages']); // Get unread notifications from any user to user1. $messages = core_message_external::get_messages($user1->id, 0, 'notifications', false, true, 0, 0); $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); $this->assertCount(0, $messages['messages']); // Get read both type of messages from any user to user1. $messages = core_message_external::get_messages($user1->id, 0, 'both', true, true, 0, 0); $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); $this->assertCount(4, $messages['messages']); // Get read notifications from no-reply-user to user1. $messages = core_message_external::get_messages($user1->id, $userfrom->id, 'notifications', true, true, 0, 0); $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); $this->assertCount(1, $messages['messages']); // Get notifications send by user1 to any user. $messages = core_message_external::get_messages(0, $user1->id, 'notifications', true, true, 0, 0); $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); $this->assertCount(1, $messages['messages']); // Test warnings. $CFG->messaging = 0; $messages = core_message_external::get_messages(0, $user1->id, 'both', true, true, 0, 0); $messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages); $this->assertCount(1, $messages['warnings']); // Test exceptions. // Messaging disabled. try { $messages = core_message_external::get_messages(0, $user1->id, 'conversations', true, true, 0, 0); $this->fail('Exception expected due messaging disabled.'); } catch (moodle_exception $e) { $this->assertEquals('disabled', $e->errorcode); } $CFG->messaging = 1; // Invalid users. try { $messages = core_message_external::get_messages(0, 0, 'conversations', true, true, 0, 0); $this->fail('Exception expected due invalid users.'); } catch (moodle_exception $e) { $this->assertEquals('accessdenied', $e->errorcode); } // Invalid user ids. try { $messages = core_message_external::get_messages(2500, 0, 'conversations', true, true, 0, 0); $this->fail('Exception expected due invalid users.'); } catch (moodle_exception $e) { $this->assertEquals('invaliduser', $e->errorcode); } // Invalid users (permissions). $this->setUser($user2); try { $messages = core_message_external::get_messages(0, $user1->id, 'conversations', true, true, 0, 0); $this->fail('Exception expected due invalid user.'); } catch (moodle_exception $e) { $this->assertEquals('accessdenied', $e->errorcode); } }
/** * Test message_get_contacts. */ public function test_message_get_contacts() { global $USER, $CFG; // Set this user as the admin. $this->setAdminUser(); $noreplyuser = core_user::get_noreply_user(); $supportuser = core_user::get_support_user(); // Create a user to add to the admin's contact list. $user1 = $this->getDataGenerator()->create_user(); $user2 = $this->getDataGenerator()->create_user(); $user3 = $this->getDataGenerator()->create_user(); // Stranger. // Add users to the admin's contact list. message_add_contact($user1->id); message_add_contact($user2->id); // Send some messages. $this->send_fake_message($user1, $USER); $this->send_fake_message($user2, $USER); $this->send_fake_message($user3, $USER); list($onlinecontacts, $offlinecontacts, $strangers) = message_get_contacts(); $this->assertCount(0, $onlinecontacts); $this->assertCount(2, $offlinecontacts); $this->assertCount(1, $strangers); // Send message from noreply and support users. $this->send_fake_message($noreplyuser, $USER); $this->send_fake_message($supportuser, $USER); list($onlinecontacts, $offlinecontacts, $strangers) = message_get_contacts(); $this->assertCount(0, $onlinecontacts); $this->assertCount(2, $offlinecontacts); $this->assertCount(3, $strangers); // Block 1 user. message_block_contact($user2->id); list($onlinecontacts, $offlinecontacts, $strangers) = message_get_contacts(); $this->assertCount(0, $onlinecontacts); $this->assertCount(1, $offlinecontacts); $this->assertCount(3, $strangers); // Noreply user being valid user. core_user::reset_internal_users(); $CFG->noreplyuserid = $user3->id; $noreplyuser = core_user::get_noreply_user(); list($onlinecontacts, $offlinecontacts, $strangers) = message_get_contacts(); $this->assertCount(0, $onlinecontacts); $this->assertCount(1, $offlinecontacts); $this->assertCount(2, $strangers); }
/** * Creates single message for all notification and sends it out * * @param object $badge A badge which is notified about. */ function badge_assemble_notification(stdClass $badge) { global $DB; $userfrom = core_user::get_noreply_user(); $userfrom->maildisplay = true; if ($msgs = $DB->get_records_select('badge_issued', 'issuernotified IS NULL AND badgeid = ?', array($badge->id))) { // Get badge creator. $creator = $DB->get_record('user', array('id' => $badge->creator), '*', MUST_EXIST); $creatorsubject = get_string('creatorsubject', 'badges', $badge->name); $creatormessage = ''; // Put all messages in one digest. foreach ($msgs as $msg) { $issuedlink = html_writer::link(new moodle_url('/badges/badge.php', array('hash' => $msg->uniquehash)), $badge->name); $recipient = $DB->get_record('user', array('id' => $msg->userid), '*', MUST_EXIST); $a = new stdClass(); $a->user = fullname($recipient); $a->link = $issuedlink; $creatormessage .= get_string('creatorbody', 'badges', $a); $DB->set_field('badge_issued', 'issuernotified', time(), array('badgeid' => $msg->badgeid, 'userid' => $msg->userid)); } // Create a message object. $eventdata = new stdClass(); $eventdata->component = 'moodle'; $eventdata->name = 'badgecreatornotice'; $eventdata->userfrom = $userfrom; $eventdata->userto = $creator; $eventdata->notification = 1; $eventdata->subject = $creatorsubject; $eventdata->fullmessage = format_text_email($creatormessage, FORMAT_HTML); $eventdata->fullmessageformat = FORMAT_PLAIN; $eventdata->fullmessagehtml = $creatormessage; $eventdata->smallmessage = $creatorsubject; message_send($eventdata); } }