protected function readquestions($lines) { // For this class the method has been simplified as // there can never be more than one question for a // multianswer import $questions = array(); $questiontext = array(); $questiontext['text'] = implode('', $lines); $questiontext['format'] = 0; $questiontext['itemid'] = ''; $question = qtype_multianswer_extract_question($questiontext); $question->questiontext = $question->questiontext['text']; $question->questiontextformat = 0; $question->qtype = MULTIANSWER; $question->generalfeedback = ''; $question->course = $this->course; if (!empty($question)) { $name = html_to_text(implode(' ', $lines)); $name = preg_replace('/{[^}]*}/', '', $name); $name = trim($name); if ($name) { $question->name = shorten_text($name, 45); } else { // We need some name, so use the current time, since that will be // reasonably unique. $question->name = userdate(time()); } $questions[] = $question; } return $questions; }
function direct($to_email, $subject = '', $body_html = '') { $body_text = html_to_text($body_html); $this->CI->load->library('composer/lib_aws'); $ses_client = $this->CI->lib_aws->get_ses(); try { $result = $ses_client->sendEmail(['Destination' => ['ToAddresses' => [$to_email]], 'Message' => ['Body' => ['Html' => ['Data' => $body_html], 'Text' => ['Data' => $body_text]], 'Subject' => ['Data' => $subject]], 'Source' => '"' . app_name() . '" <' . getenv('email_postmaster') . '>']); } catch (AwsException $e) { // handle the error. $error_msg = 'getAwsRequestId: ' . $e->getAwsRequestId() . ', getAwsErrorType:' . $e->getAwsErrorType() . ', getAwsErrorCode:' . $e->getAwsErrorCode() . "\n\n"; $error_msg .= $e->getMessage() . "\n"; $error_msg .= $e->getTraceAsString(); } if (empty($result)) { $this->error = ['message' => $error_msg]; return NULL; } else { if (!empty($result['MessageId'])) { $result = $result->toArray(); return $result; } else { $this->error = ['message' => 'Result missing MessageId', 'result' => $result]; return NULL; } } }
/** * Runs and exports, through email, the report instance specified by the * provided report schedule * * @param stdClass $report_schedule The PHP report schedule containing the information * about the specific report to be exported * * @return boolean true on success, otherwise false */ function php_report_schedule_export_instance($report_schedule, $now = 0) { global $CFG, $USER; if ($now == 0) { $now = time(); } $data = unserialize($report_schedule->config); // Create report to be emailed to recipient $shortname = $report_schedule->report; $format = $data['format']; // Initialize a temp path name $tmppath = '/temp'; // Create a unique temporary filename to use for this schedule $filename = tempnam($CFG->dataroot.$tmppath, 'php_report_'); $parameterdata = $data['parameters']; // Generate the report file $result = php_report::export_default_instance($shortname, $format, $filename, $parameterdata, $report_schedule->userid, php_report::EXECUTION_MODE_SCHEDULED); if (!$result) { //handle failure case unlink($filename); return false; } // Attach filename to an email - so get recipient... $recipients_array = explode(',',$data['recipients']); $from = get_string('noreplyname'); $subject = get_string('email_subject','local_elisreports').$data['label']; $messagetext = html_to_text($data['message']); $messagehtml = $data['message']; $start = strlen($CFG->dataroot); $attachment = substr($filename,$start); $attachname = $report_schedule->report.$now.'.'.$data['format']; // $user->id & all other fields now required by Moodle 2.6+ email_to_user() API which also calls fullname($user) $user = new stdClass; $allfields = get_all_user_name_fields(); foreach ($allfields as $field) { $user->$field = null; } $user->id = $USER->id; // let's just use this user as default (TBD) $user->mailformat = 1; // Attach the file to the recipients foreach ($recipients_array as $recipient) { $user->email = trim($recipient); email_to_user($user, $from, $subject, $messagetext, $messagehtml, $attachment, $attachname); } // Remove the file that was created for this report unlink($filename); return true; }
public function summarise_response(array $response) { if (isset($response['answer'])) { $formatoptions = new stdClass(); $formatoptions->para = false; return html_to_text(format_text($response['answer'], FORMAT_HTML, $formatoptions), 0, false); } else { return null; } }
/** * This plugin sends users a welcome message after logging in * and notify a moderator a new user has been added * it has a settings page that allow you to configure the messages * send. * * @package local * @subpackage welcome * @copyright 2014 Bas Brands, basbrands.nl, bas@sonsbeekmedia.nl * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ function send_welcome($user) { global $CFG, $SITE; $moderator = get_admin(); $sender = get_admin(); if (!empty($user->email)) { $config = get_config('local_welcome'); if (!empty($config->auth_plugins)) { $auths = explode(',', $config->auth_plugins); if (!in_array($user->auth, $auths)) { return ''; } } else { return ''; } $moderator->email = $config->moderator_email; $sender->email = $config->sender_email; $sender->firstname = $config->sender_firstname; $sender->lastname = $config->sender_lastname; $message_user_enabled = $config->message_user_enabled; $message_user = $config->message_user; $message_user_subject = $config->message_user_subject; $message_moderator_enabled = $config->message_moderator_enabled; $message_moderator = $config->message_moderator; $message_moderator_subject = $config->message_moderator_subject; if (!empty($user->country)) { $user->country = get_string($user->country, 'countries'); } else { $user->country = ''; } $sitelink = html_writer::link(new moodle_url('/'), $SITE->fullname); $resetpasswordlink = html_writer::link(new moodle_url('/login/forgot_password.php'), get_string('resetpass', 'local_welcome')); $fields = array('[[fullname]]', '[[username]]', '[[firstname]]', '[[lastname]]', '[[email]]', '[[city]]', '[[country]]', '[[sitelink]]', '[[sitename]]', '[[resetpasswordlink]]'); $values = array(fullname($user), $user->username, $user->firstname, $user->lastname, $user->email, $user->city, $user->country, $sitelink, $SITE->fullname, $resetpasswordlink); $message_user = str_replace($fields, $values, $message_user); $message_user_subject = str_replace($fields, $values, $message_user_subject); $message_moderator = str_replace($fields, $values, $message_moderator); $message_moderator_subject = str_replace($fields, $values, $message_moderator_subject); if (!empty($message_user) && !empty($sender->email) && $message_user_enabled) { email_to_user($user, $sender, $message_user_subject, html_to_text($message_user), $message_user); } if (!empty($message_moderator) && !empty($sender->email) && $message_moderator_enabled) { email_to_user($moderator, $sender, $message_moderator_subject, html_to_text($message_moderator), $message_moderator); } } }
/** * Runs and exports, through email, the report instance specified by the * provided report schedule * * @param stdClass $report_schedule The PHP report schedule containing the information * about the specific report to be exported * * @return boolean true on success, otherwise false */ function php_report_schedule_export_instance($report_schedule, $now = 0) { global $CFG; if ($now == 0) { $now = gmmktime(); // time(); } $data = unserialize($report_schedule->config); // Create report to be emailed to recipient $shortname = $report_schedule->report; $format = $data['format']; // Initialize a temp path name $tmppath = '/temp'; // Create a unique temporary filename to use for this schedule $filename = tempnam($CFG->dataroot . $tmppath, 'php_report_'); $parameterdata = $data['parameters']; // Generate the report file $result = php_report::export_default_instance($shortname, $format, $filename, $parameterdata, $report_schedule->userid, php_report::EXECUTION_MODE_SCHEDULED); if (!$result) { //handle failure case unlink($filename); return false; } // Attach filename to an email - so get recipient... $recipients_array = explode(',', $data['recipients']); $from = get_string('noreplyname'); $subject = get_string('email_subject', 'block_php_report') . $data['label']; $messagetext = html_to_text($data['message']); $messagehtml = $data['message']; $start = strlen($CFG->dataroot); $attachment = substr($filename, $start); $attachname = $report_schedule->report . $now . '.' . $data['format']; // Attach the file to the recipients foreach ($recipients_array as $recipient) { $user = new stdClass(); $user->email = $recipient; $user->mailformat = 1; email_to_user($user, $from, $subject, $messagetext, $messagehtml, $attachment, $attachname); } // Remove the file that was created for this report unlink($filename); return true; }
public function readquestions($lines) { question_bank::get_qtype('multianswer'); // Ensure the multianswer code is loaded. // For this class the method has been simplified as // there can never be more than one question for a // multianswer import. $questions = array(); $questiontext = array(); $questiontext['text'] = implode('', $lines); $questiontext['format'] = FORMAT_MOODLE; $questiontext['itemid'] = ''; $question = qtype_multianswer_extract_question($questiontext); $question->questiontext = $question->questiontext['text']; $question->questiontextformat = 0; $question->qtype = 'multianswer'; $question->generalfeedback = ''; $question->generalfeedbackformat = FORMAT_MOODLE; $question->length = 1; $question->penalty = 0.3333333; if (!empty($question)) { $name = html_to_text(implode(' ', $lines)); $name = preg_replace('/{[^}]*}/', '', $name); $name = trim($name); if ($name) { $question->name = shorten_text($name, 45); } else { // We need some name, so use the current time, since that will be // reasonably unique. $question->name = userdate(time()); } $questions[] = $question; } return $questions; }
/** * */ protected function replacements(array $patterns, $entry, array $options = null) { $field = $this->_field; $fieldname = $field->name; $edit = !empty($options['edit']); $haseditreplacement = false; $editablepatterns = array("[[{$fieldname}]]", "[[{$fieldname}:text]]", "[[{$fieldname}:textlinks]]"); $replacements = array_fill_keys(array_keys($patterns), ''); foreach ($patterns as $pattern => $cleanpattern) { if ($edit and !$haseditreplacement) { $patterneditable = in_array($cleanpattern, $editablepatterns); if ($patterneditable and !($noedit = $this->is_noedit($pattern))) { $required = $this->is_required($pattern); $editparams = array($entry, array('required' => $required)); $replacements[$pattern] = array(array($this, 'display_edit'), $editparams); $haseditreplacement = true; continue; } } switch ($cleanpattern) { case "[[{$fieldname}]]": $replacements[$pattern] = $this->display_browse($entry); break; // Plain text, no links. // Plain text, no links. case "[[{$fieldname}:text]]": $replacements[$pattern] = html_to_text($this->display_browse($entry, array('text' => true))); break; // Plain text, with links. // Plain text, with links. case "[[{$fieldname}:textlinks]]": $replacements[$pattern] = $this->display_browse($entry, array('text' => true, 'links' => true)); break; case "[[{$fieldname}:wordcount]]": $replacements[$pattern] = $this->word_count($entry); break; } } return $replacements; }
function atom_add_items($items) { global $CFG; $result = ''; $xhtmlattr = array('type' => 'xhtml'); if (!empty($items)) { foreach ($items as $item) { $result .= atom_start_tag('entry', 1, true); $result .= atom_full_tag('title', 2, false, htmlspecialchars(html_to_text($item->title))); $result .= atom_full_tag('link', 2, false, null, array('href' => $item->link, 'rel' => 'alternate')); $result .= atom_full_tag('updated', 2, false, date_format_rfc3339($item->pubdate)); //Include the author if exists if (isset($item->author)) { $result .= atom_start_tag('author', 2, true); $result .= atom_full_tag('name', 3, false, $item->author); $result .= atom_end_tag('author', 2, true); } $result .= atom_full_tag('content', 2, false, '<div xmlns="http://www.w3.org/1999/xhtml">' . clean_text($item->description, FORMAT_HTML) . '</div>', $xhtmlattr); $result .= atom_full_tag('id', 2, false, $item->link); if (isset($item->tags)) { $tagdata = array(); if (isset($item->tagscheme)) { $tagdata['scheme'] = $item->tagscheme; } foreach ($item->tags as $tag) { $tagdata['term'] = $tag; $result .= atom_full_tag('category', 2, true, false, $tagdata); } } $result .= atom_end_tag('entry', 1, true); } } else { $result = false; } return $result; }
/** * @return string a summary of a manual comment action. * @param unknown_type $step */ protected function summarise_manual_comment($step) { $a = new stdClass(); if ($step->has_behaviour_var('comment')) { $a->comment = shorten_text(html_to_text($this->format_comment( $step->get_behaviour_var('comment')), 0, false), 200); } else { $a->comment = ''; } $mark = $step->get_behaviour_var('mark'); if (is_null($mark) || $mark === '') { return get_string('commented', 'question', $a->comment); } else { $a->mark = $mark / $step->get_behaviour_var('maxmark') * $this->qa->get_max_mark(); return get_string('manuallygraded', 'question', $a); } }
/** * Send a message from one user to another. Will be delivered according to the message recipients messaging preferences * * @param object $userfrom the message sender * @param object $userto the message recipient * @param string $message the message * @param int $format message format such as FORMAT_PLAIN or FORMAT_HTML * @return int|false the ID of the new message or false */ function message_post_message($userfrom, $userto, $message, $format) { global $SITE, $CFG, $USER; $eventdata = new stdClass(); $eventdata->component = 'moodle'; $eventdata->name = 'instantmessage'; $eventdata->userfrom = $userfrom; $eventdata->userto = $userto; //using string manager directly so that strings in the message will be in the message recipients language rather than the senders $eventdata->subject = get_string_manager()->get_string('unreadnewmessage', 'message', fullname($userfrom), $userto->lang); if ($format == FORMAT_HTML) { $eventdata->fullmessagehtml = $message; //some message processors may revert to sending plain text even if html is supplied //so we keep both plain and html versions if we're intending to send html $eventdata->fullmessage = html_to_text($eventdata->fullmessagehtml); } else { $eventdata->fullmessage = $message; $eventdata->fullmessagehtml = ''; } $eventdata->fullmessageformat = $format; $eventdata->smallmessage = $message;//store the message unfiltered. Clean up on output. $s = new stdClass(); $s->sitename = format_string($SITE->shortname, true, array('context' => context_course::instance(SITEID))); $s->url = $CFG->wwwroot.'/message/index.php?user='******'&id='.$userfrom->id; $emailtagline = get_string_manager()->get_string('emailtagline', 'message', $s, $userto->lang); if (!empty($eventdata->fullmessage)) { $eventdata->fullmessage .= "\n\n---------------------------------------------------------------------\n".$emailtagline; } if (!empty($eventdata->fullmessagehtml)) { $eventdata->fullmessagehtml .= "<br /><br />---------------------------------------------------------------------<br />".$emailtagline; } $eventdata->timecreated = time(); $eventdata->notification = 0; return message_send($eventdata); }
/** * Given text in a variety of format codings, this function returns the text as plain text suitable for plain email. * * @param string $text The text to be formatted. This is raw text originally from user input. * @param int $format Identifier of the text format to be used * [FORMAT_MOODLE, FORMAT_HTML, FORMAT_PLAIN, FORMAT_WIKI, FORMAT_MARKDOWN] * @return string */ function format_text_email($text, $format) { switch ($format) { case FORMAT_PLAIN: return $text; break; case FORMAT_WIKI: // There should not be any of these any more! $text = wikify_links($text); return core_text::entities_to_utf8(strip_tags($text), true); break; case FORMAT_HTML: return html_to_text($text); break; case FORMAT_MOODLE: case FORMAT_MARKDOWN: default: $text = wikify_links($text); return core_text::entities_to_utf8(strip_tags($text), true); break; } }
/** * Returns the name of column in export * @param object $grade_item * @param boolean $feedback feedback colum * @param string $gradedisplayname grade display name. * @return string */ public function format_column_name($grade_item, $feedback = false, $gradedisplayname = null) { $column = new stdClass(); if ($grade_item->itemtype == 'mod') { $column->name = get_string('modulename', $grade_item->itemmodule) . get_string('labelsep', 'langconfig') . $grade_item->get_name(); } else { $column->name = $grade_item->get_name(); } // We can't have feedback and display type at the same time. $column->extra = $feedback ? get_string('feedback') : get_string($gradedisplayname, 'grades'); return html_to_text(get_string('gradeexportcolumntype', 'grades', $column), 0, false); }
/** * Returns array of critical errors in plain text format * @param array $environment_results array of results gathered * @return array errors */ function environment_get_errors($environment_results) { global $CFG; $errors = array(); // Iterate over each environment_result foreach ($environment_results as $environment_result) { $type = $environment_result->getPart(); $info = $environment_result->getInfo(); $status = $environment_result->getStatus(); $error_code = $environment_result->getErrorCode(); $a = new stdClass(); if ($error_code) { $a->error_code = $error_code; $errors[] = array($info, get_string('environmentxmlerror', 'admin', $a)); return $errors; } /// Calculate the status value if ($environment_result->getBypassStr() != '') { // not interesting continue; } else { if ($environment_result->getRestrictStr() != '') { // error } else { if ($status) { // ok continue; } else { if ($environment_result->getLevel() == 'optional') { // just a warning continue; } else { // error } } } } // We are comparing versions $rec = new stdClass(); if ($rec->needed = $environment_result->getNeededVersion()) { $rec->current = $environment_result->getCurrentVersion(); if ($environment_result->getLevel() == 'required') { $stringtouse = 'environmentrequireversion'; } else { $stringtouse = 'environmentrecommendversion'; } // We are checking installed & enabled things } else { if ($environment_result->getPart() == 'custom_check') { if ($environment_result->getLevel() == 'required') { $stringtouse = 'environmentrequirecustomcheck'; } else { $stringtouse = 'environmentrecommendcustomcheck'; } } else { if ($environment_result->getPart() == 'php_setting') { if ($status) { $stringtouse = 'environmentsettingok'; } else { if ($environment_result->getLevel() == 'required') { $stringtouse = 'environmentmustfixsetting'; } else { $stringtouse = 'environmentshouldfixsetting'; } } } else { if ($environment_result->getLevel() == 'required') { $stringtouse = 'environmentrequireinstall'; } else { $stringtouse = 'environmentrecommendinstall'; } } } } $report = get_string($stringtouse, 'admin', $rec); // Here we'll store all the feedback found $feedbacktext = ''; // Append the feedback if there is some $feedbacktext .= $environment_result->strToReport($environment_result->getFeedbackStr(), 'error'); // Append the restrict if there is some $feedbacktext .= $environment_result->strToReport($environment_result->getRestrictStr(), 'error'); $report .= html_to_text($feedbacktext); if ($environment_result->getPart() == 'custom_check') { $errors[] = array($info, $report); } else { $errors[] = array($info !== '' ? "{$type} {$info}" : $type, $report); } } return $errors; }
protected function bootstrap_process_message($message) { global $DB; $messagecontent = new stdClass(); if ($message->notification) { $messagecontent->text = get_string('unreadnewnotification', 'message'); } else { if ($message->fullmessageformat == FORMAT_HTML) { $message->smallmessage = html_to_text($message->smallmessage); } if (core_text::strlen($message->smallmessage) > 15) { $messagecontent->text = core_text::substr($message->smallmessage, 0, 15) . '...'; } else { $messagecontent->text = $message->smallmessage; } } if (time() - $message->timecreated <= 3600 * 3) { $messagecontent->date = format_time(time() - $message->timecreated); } else { $messagecontent->date = userdate($message->timecreated, get_string('strftimetime', 'langconfig')); } $messagecontent->from = $DB->get_record('user', array('id' => $message->useridfrom)); return $messagecontent; }
function update_authoriser($form, $data, $authoriser_id) { // Update the stored authorisation requests read_form_auths($data->id, $auth); if ($authoriser_id == 0) { delete_form_auths($auth); } else { $auth->authoriser = $authoriser_id; $auth->request_date = time(); write_form_auths($auth); } // Determine the URL to use to link to the form $program = new moodle_url('/local/obu_forms/process.php') . '?id=' . $data->id; // Email the new status to the author and to Student Central (if not the next authoriser) $author = get_complete_user_data('id', $data->author); $sc = get_complete_user_data('username', 'csa'); $sc_id = $sc->id; if (!$form->modular) { // Use the default CSA Team contact and notification details (PG) $sc_contact = $sc; $sc_notifications = $sc; } else { // Use the SCAT contact and notification details (UMP) $sc_contact = get_complete_user_data('username', 'scat'); $sc_notifications = get_complete_user_data('username', 'scat_notifications'); } // Add email headers to help prevent auto-responders $author->customheaders = array('Precedence: Bulk', 'X-Auto-Response-Suppress: All', 'Auto-Submitted: auto-generated'); $sc_contact->customheaders = array('Precedence: Bulk', 'X-Auto-Response-Suppress: All', 'Auto-Submitted: auto-generated'); get_form_status($author->id, $form, $data, $text, $button_text); // get the status from the author's perspective // If a staff form, extract any given student number $student_number = ''; if (!$form->student) { load_form_fields($data, $fields); if (array_key_exists('student_number', $fields)) { $student_number = ' [' . $fields['student_number'] . ']'; } } $html = '<h4><a href="' . $program . '">' . $form->formref . ': ' . $form->name . $student_number . '</a></h4>' . $text; email_to_user($author, $sc_contact, 'The Status of Your Form ' . $form->formref . $student_number, html_to_text($html), $html); if ($authoriser_id != $sc_id) { get_form_status($sc_id, $form, $data, $text, $button_text); // get the status from the perspective of Student Central $html = '<h4><a href="' . $program . '">' . $form->formref . ': ' . $form->name . $student_number . '</a></h4>' . $text; email_to_user($sc_notifications, $author, 'Form ' . $form->formref . $student_number . ' Status Update (' . $author->username . ')', html_to_text($html), $html); } // Notify the next authoriser (if there is one) if ($authoriser_id) { if ($authoriser_id == $sc_id) { $authoriser = $sc_notifications; } else { $authoriser = get_complete_user_data('id', $authoriser_id); } if ($authoriser->username != 'csa-tbd') { // No notification possible if authoriser TBD $form_link = '<a href="' . $program . '">' . $form->formref . ' ' . get_string('form_title', 'local_obu_forms') . $student_number . '</a>'; $email_link = '<a href="mailto:' . $sc_contact->email . '?Subject=' . get_string('auths', 'local_obu_forms') . '" target="_top">' . $sc_contact->email . '</a>'; $html = get_string('request_authorisation', 'local_obu_forms', array('form' => $form_link, 'name' => $sc_contact->alternatename, 'phone' => $sc_contact->phone1, 'email' => $email_link)); email_to_user($authoriser, $author, 'Request for Form ' . $form->formref . $student_number . ' Authorisation (' . $author->username . ')', html_to_text($html), $html); } } }
/** * Add comment * * Through this controller only logged users can post (no anonymous comments here) * * @param void * @return null */ function add() { $this->setTemplate('add_comment'); $object_id = get_id('object_id'); $object = Objects::findObject($object_id); if (!$object instanceof ContentDataObject) { flash_error(lang('no access permissions')); ajx_current("empty"); return; } // if $comment = new Comment(); $comment_data = array_var($_POST, 'comment'); tpl_assign('comment_form_object', $object); tpl_assign('comment', $comment); tpl_assign('comment_data', $comment_data); if (is_array($comment_data)) { try { try { $attached_files = ProjectFiles::handleHelperUploads(active_context()); } catch (Exception $e) { $attached_files = null; } // try $comment->setFromAttributes($comment_data); $comment->setRelObjectId($object_id); $comment->setObjectName(substr_utf($comment->getText(), 0, 250)); DB::beginWork(); $comment->save(); $comment->addToMembers($object->getMembers()); if (is_array($attached_files)) { foreach ($attached_files as $attached_file) { $comment->attachFile($attached_file); } // foreach } // if // Subscribe user to object if (!$object->isSubscriber(logged_user())) { $object->subscribeUser(logged_user()); } // if if (strlen($comment->getText()) < 100) { $comment_head = $comment->getText(); } else { $lastpos = strpos($comment->getText(), " ", 100); if ($lastpos === false) { $comment_head = $comment->getText(); } else { $comment_head = substr($comment->getText(), 0, $lastpos) . "..."; } } $comment_head = html_to_text($comment_head); ApplicationLogs::createLog($comment, ApplicationLogs::ACTION_COMMENT, false, false, true, $comment_head); DB::commit(); flash_success(lang('success add comment')); ajx_current("reload"); } catch (Exception $e) { DB::rollback(); ajx_current("empty"); flash_error($e->getMessage()); } // try } // if }
/** * Convert the question text to plain text, so it can safely be displayed * during import to let the user see roughly what is going on. */ protected function format_question_text($question) { global $DB; $formatoptions = new stdClass(); $formatoptions->noclean = true; return html_to_text(format_text($question->questiontext, $question->questiontextformat, $formatoptions), 0, false); }
} else { if ($end_of_task) { $tip_title = lang('end of task'); $img_url = image_url('/16x16/task_end.png'); $tip_pre = 'end_'; } else { $tip_title = lang('start of task'); $img_url = image_url('/16x16/task_start.png'); $tip_pre = 'st_'; } } $tip_pre .= gen_id() . "_"; $div_prefix = 'd_ta_div_' . $tip_pre; $subject = $event->getObjectName(); $divtype = '<span class="italic">' . $tip_title . '</span> - '; $tipBody = lang('assigned to') . ': ' . clean($event->getAssignedToName()) . (trim(clean($event->getText())) != '' ? '<br><br>' . html_to_text($event->getText()) : ''); } elseif ($event instanceof ProjectEvent) { $div_prefix = 'd_ev_div_'; $subject = clean($event->getObjectName()); $img_url = image_url('/16x16/calendar.png'); $divtype = '<span class="italic">' . lang('event') . '</span> - '; $tipBody = trim(clean($event->getDescription())) != '' ? '<br>' . clean($event->getDescription()) : ''; } elseif ($event instanceof Contact) { $div_prefix = 'd_bd_div_'; $objType = 'contact'; $subject = clean($event->getObjectName()); $img_url = image_url('/16x16/contacts.png'); $divtype = '<span class="italic">' . lang('birthday') . '</span> - '; } $tipBody = str_replace("\r", '', $tipBody); $tipBody = str_replace("\n", '<br>', $tipBody);
/** * Function to be run periodically according to the moodle cron * Finds all posts that have yet to be mailed out, and mails them * out to all subscribers * * @global object * @global object * @global object * @uses CONTEXT_MODULE * @uses CONTEXT_COURSE * @uses SITEID * @uses FORMAT_PLAIN * @return void */ function forum_cron() { global $CFG, $USER, $DB; $site = get_site(); // 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(); // 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 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; } 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; } } // caching subscribed users of each forum if (!isset($subscribedusers[$forumid])) { $modcontext = context_module::instance($coursemodules[$forumid]->id); if ($subusers = forum_subscribed_users($courses[$courseid], $forums[$forumid], 0, $modcontext, "u.*")) { 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) { $urlinfo = parse_url($CFG->wwwroot); $hostname = $urlinfo['host']; foreach ($users as $userto) { @set_time_limit(120); // terminate if processing of any account takes longer than 2 minutes 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(); // set this 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) { // Set up the environment for the post, discussion, forum, course $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 if (!isset($subscribedusers[$forum->id][$userto->id])) { continue; // user does not subscribe to this forum } // 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 him/her 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); continue; } //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 continue; // Be safe and don't send it to anyone } 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 it... if (!forum_user_can_see_post($forum, $discussion, $post, NULL, $cm)) { mtrace('user '.$userto->id. ' can not see '.$post->id); continue; } // OK so we need to send the email. // Does the user want this post in a digest? If so postpone it for now. if ($userto->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 ( // Headers to make emails easier to track 'Precedence: Bulk', 'List-Id: "'.$cleanforumname.'" <moodleforum'.$forum->id.'@'.$hostname.'>', 'List-Help: '.$CFG->wwwroot.'/mod/forum/view.php?f='.$forum->id, 'Message-ID: '.forum_get_email_message_id($post->id, $userto->id, $hostname), 'X-Course-Id: '.$course->id, 'X-Course-Name: '.format_string($course->fullname, true) ); if ($post->parent) { // This post is a reply, so add headers for threading (see MDL-22551) $userfrom->customheaders[] = 'In-Reply-To: '.forum_get_email_message_id($post->parent, $userto->id, $hostname); $userfrom->customheaders[] = 'References: '.forum_get_email_message_id($post->parent, $userto->id, $hostname); } $shortname = format_string($course->shortname, true, array('context' => context_course::instance($course->id))); $postsubject = html_to_text("$shortname: ".format_string($post->subject, true)); $posttext = forum_make_mail_text($course, $cm, $forum, $discussion, $post, $userfrom, $userto); $posthtml = forum_make_mail_html($course, $cm, $forum, $discussion, $post, $userfrom, $userto); // Send the post now! mtrace('Sending ', ''); $eventdata = new stdClass(); $eventdata->component = 'mod_forum'; $eventdata->name = 'posts'; $eventdata->userfrom = $userfrom; $eventdata->userto = $userto; $eventdata->subject = $postsubject; $eventdata->fullmessage = $posttext; $eventdata->fullmessageformat = FORMAT_PLAIN; $eventdata->fullmessagehtml = $posthtml; $eventdata->notification = 1; // If forum_replytouser is not set then send mail using the noreplyaddress. if (empty($CFG->forum_replytouser)) { // Clone userfrom as it is referenced by $users. $cloneduserfrom = clone($userfrom); $cloneduserfrom->email = $CFG->noreplyaddress; $eventdata->userfrom = $cloneduserfrom; } $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); $eventdata->contexturl = "{$CFG->wwwroot}/mod/forum/discuss.php?d={$discussion->id}#p{$post->id}"; $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."); add_to_log($course->id, 'forum', 'mail error', "discuss.php?d=$discussion->id#p$post->id", substr(format_string($post->subject,true),0,30), $cm->id, $userto->id); $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 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 = $CFG->timezone; // Now see if there are any digest mails waiting to be sent, and if we should send them mtrace('Starting digest processing...'); @set_time_limit(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) { @set_time_limit(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/edit.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 = "<head>"; /* foreach ($CFG->stylesheets as $stylesheet) { //TODO: MDL-21120 $posthtml .= '<link rel="stylesheet" type="text/css" href="'.$stylesheet.'" />'."\n"; }*/ $posthtml .= "</head>\n<body id=\"email\">\n"; $posthtml .= '<p>'.get_string('digestmailheader', 'forum', $headerdata).'</p><br /><hr size="1" noshade="noshade" />'; foreach ($thesediscussions as $discussionid) { @set_time_limit(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 = ! forum_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"; $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); 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]; } } $userfrom->customheaders = array ("Precedence: Bulk"); if ($userto->maildigest == 2) { // Subjects only $by = new stdClass(); $by->name = fullname($userfrom); $by->date = userdate($post->modified); $posttext .= "\n".format_string($post->subject,true).' '.get_string("bynameondate", "forum", $by); $posttext .= "\n---------------------------------------------------------------------"; $by->name = "<a target=\"_blank\" href=\"$CFG->wwwroot/user/view.php?id=$userfrom->id&course=$course->id\">$by->name</a>"; $posthtml .= '<div><a target="_blank" href="'.$CFG->wwwroot.'/mod/forum/discuss.php?d='.$discussion->id.'#p'.$post->id.'">'.format_string($post->subject,true).'</a> '.get_string("bynameondate", "forum", $by).'</div>'; } else { // The full treatment $posttext .= forum_make_mail_text($course, $cm, $forum, $discussion, $post, $userfrom, $userto, true); $posthtml .= forum_make_mail_post($course, $cm, $forum, $discussion, $post, $userfrom, $userto, false, $canreply, true, false); // Create an array of postid's for this user to mark as read. if (!$CFG->forum_usermarksread) { $userto->markposts[$post->id] = $post->id; } } } if ($canunsubscribe) { $posthtml .= "\n<div class='mdl-right'><font size=\"1\"><a href=\"$CFG->wwwroot/mod/forum/subscribe.php?id=$forum->id\">".get_string("unsubscribe", "forum")."</a></font></div>"; } else { $posthtml .= "\n<div class='mdl-right'><font size=\"1\">".get_string("everyoneissubscribed", "forum")."</font></div>"; } $posthtml .= '<hr size="1" noshade="noshade" /></p>'; } $posthtml .= '</body>'; if (empty($userto->mailformat) || $userto->mailformat != 1) { // This user DOESN'T want to receive HTML $posthtml = ''; } $attachment = $attachname=''; // Directly email forum digests rather than sending them via messaging, use the // site shortname as 'from name', the noreply address will be used by email_to_user. $mailresult = email_to_user($userto, $site->shortname, $postsubject, $posttext, $posthtml, $attachment, $attachname); if (!$mailresult) { mtrace("ERROR!"); echo "Error: mod/forum/cron.php: Could not send out digest mail to user $userto->id ($userto->email)... not trying again.\n"; add_to_log($course->id, 'forum', 'mail digest error', '', '', $cm->id, $userto->id); } else { mtrace("success."); $usermailcount++; // Mark post as read if forum_usermarksread is set off 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; }
/** * Send welcome email to specified user. * * @param stdClass $instance * @param stdClass $user user record * @return void */ protected function email_welcome_message($instance, $user) { global $CFG, $DB; $course = $DB->get_record('course', array('id' => $instance->courseid), '*', MUST_EXIST); $context = context_course::instance($course->id); $a = new stdClass(); $a->coursename = format_string($course->fullname, true, array('context' => $context)); $a->profileurl = "{$CFG->wwwroot}/user/view.php?id={$user->id}&course={$course->id}"; if (trim($instance->customtext1) !== '') { $message = $instance->customtext1; $key = array('{$a->coursename}', '{$a->profileurl}', '{$a->fullname}', '{$a->email}'); $value = array($a->coursename, $a->profileurl, fullname($user), $user->email); $message = str_replace($key, $value, $message); if (strpos($message, '<') === false) { // Plain text only. $messagetext = $message; $messagehtml = text_to_html($messagetext, null, false, true); } else { // This is most probably the tag/newline soup known as FORMAT_MOODLE. $messagehtml = format_text($message, FORMAT_MOODLE, array('context' => $context, 'para' => false, 'newlines' => true, 'filter' => true)); $messagetext = html_to_text($messagehtml); } } else { $messagetext = get_string('welcometocoursetext', 'enrol_self', $a); $messagehtml = text_to_html($messagetext, null, false, true); } $subject = get_string('welcometocourse', 'enrol_self', format_string($course->fullname, true, array('context' => $context))); $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 = reset($rusers); } else { $contact = core_user::get_support_user(); } // Directly emailing welcome message rather than using messaging. email_to_user($user, $contact, $subject, $messagetext, $messagehtml); }
/** * Given a grade_tree element, returns an array of parameters * used to build an icon for that element. * * @param array $element An array representing an element in the grade_tree * * @return array */ public function get_params_for_iconstr($element) { $strparams = new stdClass(); $strparams->category = ''; $strparams->itemname = ''; $strparams->itemmodule = ''; if (!method_exists($element['object'], 'get_name')) { return $strparams; } $strparams->itemname = html_to_text($element['object']->get_name()); // If element name is categorytotal, get the name of the parent category if ($strparams->itemname == get_string('categorytotal', 'grades')) { $parent = $element['object']->get_parent_category(); $strparams->category = $parent->get_name() . ' '; } else { $strparams->category = ''; } $strparams->itemmodule = null; if (isset($element['object']->itemmodule)) { $strparams->itemmodule = $element['object']->itemmodule; } return $strparams; }
public function classify_response(array $response) { $parts = array(); foreach ($this->places as $place => $group) { if (!array_key_exists($this->field($place), $response) || !$response[$this->field($place)]) { $parts[$place] = question_classified_response::no_response(); continue; } $fieldname = $this->field($place); $choiceno = $this->choiceorder[$group][$response[$fieldname]]; $choice = $this->choices[$group][$choiceno]; $parts[$place] = new question_classified_response($choiceno, html_to_text($choice->text, 0, false), ($this->get_right_choice_for($place) == $response[$fieldname]) / count($this->places)); } return $parts; }
/** * @param string response is a response. * @return formatted response */ function format_response($response, $format) { $safeformatoptions = new stdClass(); $safeformatoptions->para = false; return s(html_to_text(format_text($response, FORMAT_MOODLE, $safeformatoptions), 0, false)); }
/** * Given text in a variety of format codings, this function returns * the text as plain text suitable for plain email. * * @uses FORMAT_MOODLE * @uses FORMAT_HTML * @uses FORMAT_PLAIN * @uses FORMAT_WIKI * @uses FORMAT_MARKDOWN * @param string $text The text to be formatted. This is raw text originally from user input. * @param int $format Identifier of the text format to be used * [FORMAT_MOODLE, FORMAT_HTML, FORMAT_PLAIN, FORMAT_WIKI, FORMAT_MARKDOWN] * @return string */ function format_text_email($text, $format) { switch ($format) { case FORMAT_PLAIN: return $text; break; case FORMAT_WIKI: // there should not be any of these any more! $text = wikify_links($text); return strtr(strip_tags($text), array_flip(get_html_translation_table(HTML_ENTITIES))); break; case FORMAT_HTML: return html_to_text($text); break; case FORMAT_MOODLE: case FORMAT_MARKDOWN: default: $text = wikify_links($text); return strtr(strip_tags($text), array_flip(get_html_translation_table(HTML_ENTITIES))); break; } }
/** * Returns a plain text version of the email * @return string */ function getTextBody() { if ($this->getBodyHtml()) { return html_to_text(html_entity_decode($this->getBodyHtml(),null, "UTF-8")); } else { return $this->getBodyPlain(); } }
protected function _plain_text($html) { if (!function_exists('html_to_text')) { $body = @html_entity_decode($html, ENT_QUOTES, $this->charset); // Added by Ivan Tcholakov, 28-JUL-2013. $body = preg_match('/\\<body.*?\\>(.*)\\<\\/body\\>/si', $body, $match) ? $match[1] : $body; $body = str_replace("\t", '', preg_replace('#<!--(.*)--\\>#', '', trim(strip_tags($body)))); for ($i = 20; $i >= 3; $i--) { $body = str_replace(str_repeat("\n", $i), "\n\n", $body); } // Reduce multiple spaces $body = preg_replace('| +|', ' ', $body); return $body; } // Also, a special helper function based on Markdown or Textile libraries may be used. // // An example of Markdown-based implementation, see http://milianw.de/projects/markdownify/ // // Make sure the class Markdownify_Extra is autoloaded (or simply loaded somehow). // Place in MY_html_helper.php the following function. // // function html_to_text($html) { // static $parser; // if (!isset($parser)) { // $parser = new Markdownify_Extra(); // $parser->keepHTML = false; // } // return @ $parser->parseString($html); // } // return html_to_text($html); }
function get_member_custom_property_value_for_listing($cp, $member_id, $cp_vals = null) { if (is_null($cp_vals)) { $cp_vals = MemberCustomPropertyValues::getMemberCustomPropertyValues($member_id, $cp->getId()); } $val_to_show = ""; foreach ($cp_vals as $cp_val) { if (in_array($cp->getType(), array('contact', 'user')) && $cp_val instanceof MemberCustomPropertyValue) { $cp_contact = Contacts::findById($cp_val->getValue()); if ($cp_contact instanceof Contact) { $cp_val->setValue($cp_contact->getObjectName()); } else { $cp_val->setValue(""); } } if ($cp->getType() == 'date' && $cp_val instanceof MemberCustomPropertyValue) { $format = user_config_option('date_format'); Hook::fire("custom_property_date_format", null, $format); $tmp_date = DateTimeValueLib::dateFromFormatAndString(DATE_MYSQL, $cp_val->getValue()); if (str_starts_with($cp_val->getValue(), EMPTY_DATE)) { $formatted = ""; } else { if (str_ends_with($cp_val->getValue(), "00:00:00")) { $formatted = $tmp_date->format(user_config_option('date_format')); } else { $formatted = $tmp_date->format($format); } } $cp_val->setValue($formatted); } if ($cp->getType() == 'address' && $cp_val instanceof MemberCustomPropertyValue) { $values = str_replace("\\|", "%%_PIPE_%%", $cp_val->getValue()); $exploded = explode("|", $values); foreach ($exploded as &$v) { $v = str_replace("%%_PIPE_%%", "|", $v); $v = str_replace("'", "\\'", $v); } if (count($exploded) > 0) { $address_type = array_var($exploded, 0, ''); $street = array_var($exploded, 1, ''); $city = array_var($exploded, 2, ''); $state = array_var($exploded, 3, ''); $country = array_var($exploded, 4, ''); $zip_code = array_var($exploded, 5, ''); $country_name = CountryCodes::getCountryNameByCode($country); $tmp = array(); if ($street != '') { $tmp[] = $street; } if ($city != '') { $tmp[] = $city; } if ($state != '') { $tmp[] = $state; } if ($zip_code != '') { $tmp[] = $zip_code; } if ($country_name != '') { $tmp[] = $country_name; } $cp_val->setValue(implode(' - ', $tmp)); } } $val_to_show .= ($val_to_show == "" ? "" : ", ") . ($cp_val instanceof MemberCustomPropertyValue ? $cp_val->getValue() : ""); } $val_to_show = html_to_text($val_to_show); return $val_to_show; }
/** * 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; }
/** * This plugin sends users a welcome message after logging in * and notify a moderator a new user has been added * it has a settings page that allow you to configure the messages * send. * * @package local * @subpackage welcome * @copyright 2015 Bas Brands, basbrands.nl, bas@sonsbeekmedia.nl * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ function send_welcome($user) { global $CFG, $SITE; require_once $CFG->dirroot . '/local/welcome/locallib.php'; $sender = get_admin(); if (!empty($user->email)) { $config = get_config('local_welcome'); $moderator = clone $sender; if (!empty($config->auth_plugins)) { $auths = explode(',', $config->auth_plugins); if (!in_array($user->auth, $auths)) { return ''; } } else { return ''; } $moderator->email = $config->moderator_email; $sender->email = $config->sender_email; $sender->firstname = $config->sender_firstname; $sender->lastname = $config->sender_lastname; $message_user_enabled = $config->message_user_enabled; $message_user = $config->message_user; $message_user_subject = $config->message_user_subject; $message_moderator_enabled = $config->message_moderator_enabled; $message_moderator = $config->message_moderator; $message_moderator_subject = $config->message_moderator_subject; $welcome = new local_welcome(); $message_user = $welcome->replace_values($user, $message_user); $message_user_subject = $welcome->replace_values($user, $message_user_subject); $message_moderator = $welcome->replace_values($user, $message_moderator); $message_moderator_subject = $welcome->replace_values($user, $message_moderator_subject); if (!empty($message_user) && !empty($sender->email) && $message_user_enabled) { email_to_user($user, $sender, $message_user_subject, html_to_text($message_user), $message_user); } if (!empty($message_moderator) && !empty($sender->email) && $message_moderator_enabled) { email_to_user($moderator, $sender, $message_moderator_subject, html_to_text($message_moderator), $message_moderator); } } }