Skip to content

Commit

Permalink
Merge pull request #33 from bdecentgmbh/dev
Browse files Browse the repository at this point in the history
2.0 release
  • Loading branch information
stefanscholz authored Feb 20, 2024
2 parents bdc6fdc + b868f08 commit ef12162
Show file tree
Hide file tree
Showing 16 changed files with 1,418 additions and 36 deletions.
405 changes: 405 additions & 0 deletions actions/notification/classes/helper.php

Large diffs are not rendered by default.

205 changes: 205 additions & 0 deletions actions/notification/classes/manager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

/**
* Notification pulse action - Message manager.
*
* @package pulseaction_notification
* @copyright 2023, bdecent gmbh bdecent.de
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

namespace pulseaction_notification;

use core\message\message;

/**
* Helps to send messages from available message processesors, extends the moodle core\message\manager method.
*/
class manager extends \core\message\manager {

/**
* Do the message sending - The method to use the custom call_processor method.
*
* NOTE: to be used from message_send() only.
*
* @copyright 2014 Totara Learning Solutions Ltd {@link http://www.totaralms.com/}
* @author Petr Skoda <[email protected]>
*
* @param \core\message\message $eventdata fully prepared event data for processors
* @param \stdClass $savemessage the message saved in 'message' table
* @param array $processorlist list of processors for target user
* @return int $messageid the id from 'messages' (false is not returned)
*/
public static function send_message(message $eventdata, \stdClass $savemessage, array $processorlist) {
global $CFG;

require_once($CFG->dirroot.'/message/lib.php'); // This is most probably already included from messagelib.php file.

if (empty($processorlist)) {
// Trigger event for sending a message or notification - we need to do this before marking as read!
self::trigger_message_events($eventdata, $savemessage);

if ($eventdata->notification) {
// If they have deselected all processors and it's a notification mark it read. The user doesn't want to be
// bothered.
$savemessage->timeread = null;
\core_message\api::mark_notification_as_read($savemessage);
} else if (empty($CFG->messaging)) {
// If it's a message and messaging is disabled mark it read.
\core_message\api::mark_message_as_read($eventdata->userto->id, $savemessage);
}

return $savemessage->id;
}

// Let the manager do the sending or buffering when db transaction in progress.
return self::send_message_to_processors($eventdata, $savemessage, $processorlist);
}

/**
* Send message to message processors - Inherit the method to use the custom call_processor method.
*
* @copyright 2014 Totara Learning Solutions Ltd {@link http://www.totaralms.com/}
* @author Petr Skoda <[email protected]>
*
* @param \stdClass|\core\message\message $eventdata
* @param \stdClass $savemessage
* @param array $processorlist
* @throws \moodle_exception
* @return int $messageid
*/
protected static function send_message_to_processors($eventdata, \stdClass $savemessage, array
$processorlist) {
global $CFG, $DB;

// We cannot communicate with external systems in DB transactions,
// buffer the messages if necessary.
if ($DB->is_transaction_started()) {
// We need to clone all objects so that devs may not modify it from outside later.
$eventdata = clone($eventdata);
$eventdata->userto = clone($eventdata->userto);
$eventdata->userfrom = clone($eventdata->userfrom);

// Conserve some memory the same was as $USER setup does.
unset($eventdata->userto->description);
unset($eventdata->userfrom->description);

self::$buffer[] = array($eventdata, $savemessage, $processorlist);
return $savemessage->id;
}

// Send the message to processors.
if (!self::call_processors($eventdata, $processorlist)) {
throw new \moodle_exception("Message was not sent.");
}

// Trigger event for sending a message or notification - we need to do this before marking as read!
self::trigger_message_events($eventdata, $savemessage);

if (!$eventdata->notification && empty($CFG->messaging)) {
// If it's a message and messaging is disabled mark it read.
\core_message\api::mark_message_as_read($eventdata->userto->id, $savemessage);
}

return $savemessage->id;
}

/**
* For each processor, call it's send_message() method
* - This method is modified version of core\message\manager call_processors.
* - Modifed to use our custom email message procesessor instead of default message_output_email method.
* - By updating the email processor pulse includes the CC and Bcc emails.
*
* @copyright 2014 Totara Learning Solutions Ltd {@link http://www.totaralms.com/}
* @author Petr Skoda <[email protected]>
*
* @param message $eventdata the message object.
* @param array $processorlist the list of processors for a single user.
* @return bool false if error calling message processor
*/
protected static function call_processors(message $eventdata, array $processorlist) {
// Allow plugins to change the message/notification data before sending it.
$pluginsfunction = get_plugins_with_function('pre_processor_message_send');
$sendmsgsuccessful = true;
foreach ($processorlist as $procname) {
// Let new messaging class add custom content based on the processor.
$proceventdata = ($eventdata instanceof message) ? $eventdata->get_eventobject_for_processor($procname) : $eventdata;

if ($pluginsfunction) {
foreach ($pluginsfunction as $plugintype => $plugins) {
foreach ($plugins as $pluginfunction) {
$pluginfunction($procname, $proceventdata);
}
}
}

$stdproc = new \stdClass();
$stdproc->name = $procname;

// Call the pulse email process instead of message_email_output.
$processor = ($procname == 'email')
? self::get_processed_processor_object($stdproc) : \core_message\api::get_processed_processor_object($stdproc);
if (!$processor->object->send_message($proceventdata)) {
debugging('Error calling message processor ' . $procname);
$sendmsgsuccessful = false;
}
}
return $sendmsgsuccessful;
}

/**
* Modified version of \core_message\api::get_processed_processor_object.
* - Fetch the pulseaction_notification_email processor. This helps to use pulse custom email processor.
*
* Given a processor object, loads information about it's settings and configurations.
* This is not a public api, instead use {@see \core_message\api::get_message_processor()}
* or {@see \get_message_processors()}
*
* @copyright 2016 Mark Nelson <[email protected]>
*
* @param \stdClass $processor processor object
* @return \stdClass processed processor object
* @since Moodle 3.2
*/
public static function get_processed_processor_object(\stdClass $processor) {
global $CFG;

$processorfile = $CFG->dirroot. '/mod/pulse/actions/notification/pulseaction_notification_email.php';
if (is_readable($processorfile)) {
include_once($processorfile);
$processclass = 'pulseaction_notification_email';
if (class_exists($processclass)) {
$pclass = new $processclass();
$processor->object = $pclass;
$processor->configured = 0;
if ($pclass->is_system_configured()) {
$processor->configured = 1;
}
$processor->hassettings = 0;
if (is_readable($CFG->dirroot.'/message/output/'.$processor->name.'/settings.php')) {
$processor->hassettings = 1;
}
$processor->available = 1;
} else {
throw new \moodle_exception('errorcallingprocessor', 'message');
}
} else {
$processor->available = 0;
}
return $processor;
}
}
8 changes: 4 additions & 4 deletions actions/notification/classes/notification.php
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,7 @@ public function create_schedule_forinstance($newenrolment=false) {
$users = $this->get_users_withroles($roles, $context);
foreach ($users as $userid => $user) {
$suppressreached = notify_users::is_suppress_reached(
$this->notificationdata, $userid, $this->instancedata->course, null);
$this->notificationdata, $user->id, $this->instancedata->course, null);
if ($suppressreached) {
continue;
}
Expand Down Expand Up @@ -730,7 +730,7 @@ protected function get_users_withroles(array $roles, $context, $childuserid=null
list($insql, $inparams) = $DB->get_in_or_equal($roles, SQL_PARAMS_NAMED, 'rle');

// TODO: Define user fields, never get entire fields.
$rolesql = "SELECT DISTINCT u.id, u.*, ra.roleid FROM {role_assignments} ra
$rolesql = "SELECT ra.id as assignid, u.*, ra.roleid FROM {role_assignments} ra
JOIN {user} u ON u.id = ra.userid
JOIN {role} r ON ra.roleid = r.id
LEFT JOIN {role_names} rn ON (rn.contextid = :ctxid AND rn.roleid = r.id) ";
Expand Down Expand Up @@ -922,8 +922,8 @@ public function generate_notification_details($moddata, $user, $context, $notifi

$result = [
'recepient' => (object) $user,
'cc' => implode(',', array_column($ccusers, 'email')),
'bcc' => implode(',', array_column($bccusers, 'email')),
'cc' => array_map(fn($user) => [$user->email, fullname($user)], $ccusers),
'bcc' => array_map(fn($user) => [$user->email, fullname($user)], $bccusers),
'subject' => format_string($this->notificationdata->subject),
'content' => $this->build_notification_content($moddata, $context, $notificationoverrides),
];
Expand Down
10 changes: 4 additions & 6 deletions actions/notification/classes/schedule.php
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,8 @@ public function send_scheduled_notification($userid=null) {
$sender = $this->find_sender_user();

// Add bcc and CC to sender user custom headers.
$sender->customheaders = [
"Bcc: $detail->bcc\r\n",
"Cc: $detail->cc\r\n",
];
$cc = $detail->cc ?? [];
$bcc = $detail->bcc ?? [];

// Prepare the module data. based on dynamic content and includ the session data.
$mod = $this->prepare_moduledata_placeholders($modules, $cmdata);
Expand All @@ -195,8 +193,8 @@ public function send_scheduled_notification($userid=null) {
$pulse = (object) ['course' => $this->course->id];
// TODO: NOTE using notification API takes 16 queries. Direct email_to_user method will take totally 9 queries.
// Send the notification to user.
$messagesend = \mod_pulse\helper::messagetouser(
$detail->recepient, $subject, $messageplain, $messagehtml, $pulse, $sender
$messagesend = \pulseaction_notification\helper::messagetouser(
$detail->recepient, $subject, $messageplain, $messagehtml, $pulse, $sender, $cc, $bcc
);

if ($messagesend) {
Expand Down
Loading

0 comments on commit ef12162

Please sign in to comment.