Actions

Developer Area/Notification Plugins & Activities

From Mahara Wiki

< Developer Area

Mahara has a notification system for sending messages to users. On the implementation side, the system is divided into two parts:

  • Activities are the actions that trigger messages, such as posting to a group forum, sharing a page, joining an institution, sending a friend request, or direct messaging another user.
  • Notifications are the plugins that deliver those messages to the user. Mahara by default includes three notifications: Inbox, Email, and Email Digest.

If a Mahara user clicks on "Settings", there is a "Notifications" tab that will show up below the main nav. Clicking this takes you to that user's notification settings page. This page lists all of the different Activity types Mahara is currently aware of, and lets the user specify which Notification method they want to handle each of these (or none). It's worth noting, if the user picks a notification method other than "Inbox", they will still receive a notification in their Inbox, but it will be automatically marked "read".

The notification life-cycle

  1. A piece of Mahara code calls the method activity_occurred($activitytype, $data, $plugintype=null, $pluginname=null, $delay=null)
    1. If the $delay field is true, or if the activity is marked for delay in the activity_type table in the database, then the activity is inserted into the activity_queue table to be handled by the cron job.
    2. Otherwise, the activity is handled immediately.
  2. When the activity is handled, its ActivityType subclass is instantiated, and its notify_users() method is called. This in turn calls the singular notify_user() once for each user.
  3. The notify_user() method then looks up the user's preference for which Notification type should be used for this Activity. It calls the appropriate PluginNotification subclass's static notify_user() method. The PluginNotification subclass then sends the message to the user in some way.
  4. To ensure that notifications also show up in the user's inbox, the ActivityType also calls PluginNotificationInternal::notify_user(). If their notification preference was for inbox, it marks the message "unread". Otherwise, it marks it "read".

Sending a notification

As a developer, if you wish to send a notification for an existing activity type, all you need to do is call the activity_occurred() method.

// Core activity
activity_occurred('activitytype', $data);

// Plugin activity
activity_occurred('activitytype', $data, $plugintype, $pluginname);

// Force the notification to be queued to the cron.
activity_occurred('activitytype', $data, null, null, true);

The $data to include will depend upon the ActivityType's get_required_params() method. You do not need to specify the Notification type, because that will be determined by the user's preferences.

If you want to create a new activity type, you'll need to implement an ActivityType subclass, as described in the next section.

Activities

Activities are the things users can do that generate messages. Looked at another way, they're the thing you call to generate the appropriate message for the appropriate audience when a user takes a particular action.

Activities are an API, but not a full-fledged plugin. Each Activity is defined by a class that extends ActivityType. Core activities are defined in lib/activity.php.

Plugins can also define their own activity types, in their lib.php file. Plugin activities should follow the naming pattern "ActivityType{$plugintype}{$pluginname}{$activityname}". For example, the "feedback" activity of the "comment" Artefact is called ActivityTypeArtefactCommentFeedback.

The bare minimum to implement

1. __construct($data, $cron = false)

It's poorly documented, but an ActivityType's constructor is meant to call the parent constructor, and then populate $this->users with a list of user records which should receive the message. The $data parameter will be an object, passed in by the call to activity_occurred().

public function __construct($data, $cron = false) {
    parent::__construct($data, $cron);
    $this->users = $this->get_my_users();
}

2. get_required_parameters()

This method should return an array which names the fields that must be present in $data. It should include all necessary data to determine the recipient(s) of the notification, as well as its content.

Also recommended

To specify the content of the message, you will additionally need to override get_message() and get_subject(), or override the $this->strings field to indicate the appropriate lang strings (see ActivityType->get_string_for_user() for the gory details of that approach).

You should not override the notify_users() and notify_user() methods, as they specify important details of how the class interacts with the PluginType classes. We should probably mark those "final".

The activity_type table

All activities that Mahara knows about are listed in the activity_type table in the database. Core activities are inserted here by one of Mahara's post-installation methods. Plugin activities are installed by the plugin_upgrade() method at install or upgrade time.

The one interesting thing about this table is that it includes a delay column, which can be "0" or "1". If it's 1, then notifications for this activity will always be queued and handled by the cron job, regardless of whether the user specifies $delay=true when calling activity_occurred().

Notifications

Notifications are the methods by which users receive messages (email, email digest, SMS text message, etc).

Notifications are a full-fledged Plugin type in Mahara, with their own lang files, cron table, config table, etc, living under the "/notification" folder, and implemented by subclassing PluginNotification. The "emaildigest" notification type, for instance, uses its cron job to gather each day's emails into digest form.

The PluginNotification subclasses are never instantiated and contain only static methods. The most important method is notify_user($user, $data). This method is called once for each user who should receive a message, and it should send the message to them by whatever means the notification is meant to represent.

The plugin can specify additional data that it needs from the notification, by providing a static $userdata field, which should be an array. For each item in the array, a corresponding "get_" method will be looked for and called if present in the ActivityType method, and the result will be added to $userdata. For instance, the "email" notification adds "htmlmessage" and "emailmessage", and some ActivityTypes implement "get_htmlmessage()" and "get_emailmessage()" to provide alternate forms of the message for HTML email and standard email.

It may also be worth pointing out that "notify_user()" does not actually have to notify the user immediately. The "email digest" notification's notify_user() method inserts the message into a digest queue table, and then its cron job reads the messages out of that queue table and assembles them into digests.

See also