Skip to content

Commit

Permalink
MDL-60680 notifications: New customdata field
Browse files Browse the repository at this point in the history
New field to store custom data for message processors.
  • Loading branch information
jleyva committed Apr 23, 2019
1 parent c134381 commit 333d11c
Show file tree
Hide file tree
Showing 13 changed files with 94 additions and 6 deletions.
31 changes: 28 additions & 3 deletions lib/classes/message/message.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
* replyto string An email address which can be used to send an reply.
* attachment stored_file File instance that needs to be sent as attachment.
* attachname string Name of the attachment.
* customdata mixed Custom data to be passed to the message processor. Must be serialisable using json_encode().
*
* @package core_message
* @since Moodle 2.9
Expand Down Expand Up @@ -122,9 +123,12 @@ class message {
/** @var int The time the message was created.*/
private $timecreated;

/** @var boolean Mark trust content. */
/** @var boolean Mark trust content. */
private $fullmessagetrust;

/** @var mixed Custom data to be passed to the message processor. Must be serialisable using json_encode(). */
private $customdata;

/** @var array a list of properties that is allowed for each message. */
private $properties = array(
'courseid',
Expand All @@ -148,8 +152,9 @@ class message {
'attachment',
'attachname',
'timecreated',
'fullmessagetrust'
);
'fullmessagetrust',
'customdata',
);

/** @var array property to store any additional message processor specific content */
private $additionalcontent = array();
Expand Down Expand Up @@ -199,6 +204,20 @@ protected function get_smallmessage($processorname = '') {
}
}

/**
* Always JSON encode customdata.
*
* @param mixed $customdata a data structure that must be serialisable using json_encode().
*/
protected function set_customdata($customdata) {
// Always include the courseid (because is not stored in the notifications or messages table).
if (!empty($this->courseid) && (is_object($customdata) || is_array($customdata))) {
$customdata = (array) $customdata;
$customdata['courseid'] = $this->courseid;
}
$this->customdata = json_encode($customdata);
}

/**
* Helper method used to get message content added with processor specific content.
*
Expand Down Expand Up @@ -251,6 +270,12 @@ public function __get($prop) {
* @throws \coding_exception
*/
public function __set($prop, $value) {

// Custom data must be JSON encoded always.
if ($prop == 'customdata') {
return $this->set_customdata($value);
}

if (in_array($prop, $this->properties)) {
return $this->$prop = $value;
}
Expand Down
3 changes: 3 additions & 0 deletions lib/db/install.xml
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,7 @@
<FIELD NAME="timeusertodeleted" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="component" TYPE="char" LENGTH="100" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="eventtype" TYPE="char" LENGTH="100" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="customdata" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="Custom data to be passed to the message processor. Must be serialisable using json_encode()"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
Expand Down Expand Up @@ -604,6 +605,7 @@
<FIELD NAME="smallmessage" TYPE="text" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="fullmessagetrust" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="customdata" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="Custom data to be passed to the message processor. Must be serialisable using json_encode()"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
Expand Down Expand Up @@ -698,6 +700,7 @@
<FIELD NAME="contexturlname" TYPE="text" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="timeread" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="customdata" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="Custom data to be passed to the message processor. Must be serialisable using json_encode()"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
Expand Down
29 changes: 29 additions & 0 deletions lib/db/upgrade.php
Original file line number Diff line number Diff line change
Expand Up @@ -3000,5 +3000,34 @@ function xmldb_main_upgrade($oldversion) {
upgrade_main_savepoint(true, 2019041300.01);
}

if ($oldversion < 2019041800.01) {
// Add new customdata field to message table.
$table = new xmldb_table('message');
$field = new xmldb_field('customdata', XMLDB_TYPE_TEXT, null, null, null, null, null, 'eventtype');

// Conditionally launch add field output.
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}

// Add new customdata field to notifications and messages table.
$table = new xmldb_table('notifications');
$field = new xmldb_field('customdata', XMLDB_TYPE_TEXT, null, null, null, null, null, 'timecreated');

// Conditionally launch add field output.
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}

$table = new xmldb_table('messages');
// Conditionally launch add field output.
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}

// Main savepoint reached.
upgrade_main_savepoint(true, 2019041800.01);
}

return true;
}
2 changes: 2 additions & 0 deletions lib/messagelib.php
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ function message_send(\core\message\message $eventdata) {
$tabledata->fullmessagehtml = $eventdata->fullmessagehtml;
$tabledata->smallmessage = $eventdata->smallmessage;
$tabledata->timecreated = time();
$tabledata->customdata = $eventdata->customdata;

// The Trusted Content system.
// Texts created or uploaded by such users will be marked as trusted and will not be cleaned before display.
Expand Down Expand Up @@ -255,6 +256,7 @@ function message_send(\core\message\message $eventdata) {
$tabledata->eventtype = $eventdata->name;
$tabledata->component = $eventdata->component;
$tabledata->timecreated = time();
$tabledata->customdata = $eventdata->customdata;
if (!empty($eventdata->contexturl)) {
$tabledata->contexturl = (string)$eventdata->contexturl;
} else {
Expand Down
7 changes: 7 additions & 0 deletions lib/tests/messagelib_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ public function test_send_message_redirection() {
$message->fullmessagehtml = '<p>message body</p>';
$message->smallmessage = 'small message';
$message->notification = '0';
$message->customdata = ['datakey' => 'data'];

$sink = $this->redirectMessages();
$this->setCurrentTimeStart();
Expand All @@ -218,6 +219,12 @@ public function test_send_message_redirection() {
$this->assertEquals($message->smallmessage, $savedmessage->smallmessage);
$this->assertEquals($message->smallmessage, $savedmessage->smallmessage);
$this->assertEquals($message->notification, $savedmessage->notification);
$this->assertEquals($message->customdata, $savedmessage->customdata);
$this->assertContains('datakey', $savedmessage->customdata);
// Check it was a unserialisable json.
$customdata = json_decode($savedmessage->customdata);
$this->assertEquals('data', $customdata->datakey);
$this->assertEquals(1, $customdata->courseid);
$this->assertTimeCurrent($savedmessage->timecreated);
$record = $DB->get_record('messages', array('id' => $savedmessage->id), '*', MUST_EXIST);
unset($savedmessage->useridto);
Expand Down
7 changes: 6 additions & 1 deletion message/externallib.php
Original file line number Diff line number Diff line change
Expand Up @@ -3116,7 +3116,12 @@ public static function get_messages_returns() {
'timecreated' => new external_value(PARAM_INT, 'Time created'),
'timeread' => new external_value(PARAM_INT, 'Time read'),
'usertofullname' => new external_value(PARAM_TEXT, 'User to full name'),
'userfromfullname' => new external_value(PARAM_TEXT, 'User from full name')
'userfromfullname' => new external_value(PARAM_TEXT, 'User from full name'),
'component' => new external_value(PARAM_TEXT, 'The component that generated the notification',
VALUE_OPTIONAL),
'eventtype' => new external_value(PARAM_TEXT, 'The type of notification', VALUE_OPTIONAL),
'customdata' => new external_value(PARAM_RAW, 'Custom data to be passed to the message processor.
The data here is serialised using json_encode().', VALUE_OPTIONAL),
), 'message'
)
),
Expand Down
2 changes: 1 addition & 1 deletion message/output/popup/classes/api.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public static function get_popup_notifications($useridto = 0, $sort = 'DESC', $l
n.subject, n.fullmessage, n.fullmessageformat,
n.fullmessagehtml, n.smallmessage, n.contexturl,
n.contexturlname, n.timecreated, n.component,
n.eventtype, n.timeread
n.eventtype, n.timeread, n.customdata
FROM {notifications} n
WHERE n.id IN (SELECT notificationid FROM {message_popup_notifications})
AND n.useridto = ?
Expand Down
2 changes: 2 additions & 0 deletions message/output/popup/externallib.php
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@ public static function get_popup_notifications_returns() {
'component' => new external_value(PARAM_TEXT, 'The component that generated the notification',
VALUE_OPTIONAL),
'eventtype' => new external_value(PARAM_TEXT, 'The type of notification', VALUE_OPTIONAL),
'customdata' => new external_value(PARAM_RAW, 'Custom data to be passed to the message processor.
The data here is serialised using json_encode().', VALUE_OPTIONAL),
), 'message'
)
),
Expand Down
1 change: 1 addition & 0 deletions message/output/popup/tests/base.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ protected function send_fake_unread_popup_notification($userfrom, $userto, $mess
$record->fullmessage = $message;
$record->smallmessage = $message;
$record->timecreated = $timecreated ? $timecreated : time();
$record->customdata = json_encode(['datakey' => 'data']);

$id = $DB->insert_record('notifications', $record);

Expand Down
2 changes: 2 additions & 0 deletions message/output/popup/tests/externallib_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ public function test_get_popup_notifications_as_recipient() {
$this->setAdminUser();
$result = message_popup_external::get_popup_notifications($recipient->id, false, 0, 0);
$this->assertCount(4, $result['notifications']);
// Check we receive custom data as a unserialisable json.
$this->assertObjectHasAttribute('datakey', json_decode($result['notifications'][0]->customdata));

$this->setUser($recipient);
$result = message_popup_external::get_popup_notifications($recipient->id, false, 0, 0);
Expand Down
5 changes: 5 additions & 0 deletions message/tests/externallib_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -1612,6 +1612,7 @@ public function test_get_messages() {
$eventdata->fullmessageformat = FORMAT_PLAIN;
$eventdata->fullmessagehtml = '<strong>Feedback submitted</strong>';
$eventdata->smallmessage = '';
$eventdata->customdata = ['datakey' => 'data'];
message_send($eventdata);

$this->setUser($user1);
Expand Down Expand Up @@ -1644,6 +1645,10 @@ public function test_get_messages() {
$messages = core_message_external::get_messages(0, $user1->id, 'notifications', true, true, 0, 0);
$messages = external_api::clean_returnvalue(core_message_external::get_messages_returns(), $messages);
$this->assertCount(1, $messages['messages']);
// Check we receive custom data as a unserialisable json.
$this->assertObjectHasAttribute('datakey', json_decode($messages['messages'][0]['customdata']));
$this->assertEquals('mod_feedback', $messages['messages'][0]['component']);
$this->assertEquals('submission', $messages['messages'][0]['eventtype']);

// Test warnings.
$CFG->messaging = 0;
Expand Down
7 changes: 7 additions & 0 deletions message/upgrade.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ information provided here is intended especially for developers.
functionality and remove all the legacy code (see MDL-63915).
Note - It's still possible to view another user's messages if you have the right capabilities and are able to
'log-in as' them.
* A new 'customdata' field for both messages and notifications has been added. This new field can store any custom data
serialised using json_encode().
This new field can be used for storing any data not fitting in the current message structure. For example, it will be used
to store additional information for the "Mobile notifications" processor.
Existing external functions: core_message_get_messages and message_popup_get_popup_notifications has been udated to return the
new field.
* External function core_message_get_messages now returns the component and eventtype.

=== 3.6 ===

Expand Down
2 changes: 1 addition & 1 deletion version.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@

defined('MOODLE_INTERNAL') || die();

$version = 2019041800.00; // YYYYMMDD = weekly release date of this DEV branch.
$version = 2019041800.01; // YYYYMMDD = weekly release date of this DEV branch.
// RR = release increments - 00 in DEV branches.
// .XX = incremental changes.

Expand Down

0 comments on commit 333d11c

Please sign in to comment.