Notifications recipients

Concepts

  • Every notifiable event resolver has a list of available recipient classes
  • Every notification has a default recipient class selected from the list of available recipient classes for the notifiable event
  • Recipient classes each provides an array of user IDs that will receive a notification
  • During sending time the recipient class is instantiated and the array of user IDs is fetched
  • Each user from this list will receive a personalised notification

GraphQL

Notification preferences (information about each notification) includes information about the selected recipient in the form of a totara_notification_recipient type:

type totara_notification_notification_preference {
# ...
  recipient: totara_notification_recipient!
# ...
}

The totara_notification_recipient type defines the recipient name and the recipient class used:

type totara_notification_recipient {
# ...
  class_name: String
  name: String
# ...
}

List of all supported recipients in specific notifiable_event is provided by recipients array field which has both class and name used in preferences.

type totara_notification_event_resolver {
# ...

  """
  The recipients for notifiable event name.
  """
  recipients: [totara_notification_recipient!]!

# ...
}

Classes/interfaces

This table outlines classes, interfaces, and methods most relevant in recipient processing.

Class, interface, or methodNotes
interface \totara_notification\recipient\recipientAll classes that represent a recipient must implement this interface.  Implementation of this interface include static name to be used in management interface and method to get all user IDs for specific instance of notification.
interface \totara_notification\event\notifiable_event::get_notification_event_dataEvery notifiable event must implement this method that returns the data associated with the event. This data will be passed down to the event resolver that will be used in determining the recipients and sending the notification.
abstract class \totara_notification\resolver\notifiable_event_resolver::get_notification_available_recipients()Every notifiable event must implement this method that returns array of classes implementing \totara_notification\recipient\recipient interface and closures methods that instantiate this class based on event_data. This list will be allow administrative users to choose recipient. 
abstract class \totara_notification\notification\built_in_notification::get_recipient_class_name()Every built-in notification must return recipient class used in notification by implementing this method. It must be in array of recipient classes returned by linked notifiable_event_resolver::get_notification_available_recipients() method.

Custom recipient implementation

Create your recipient class by implementing recipient interface in your component:

namespace your_component\totara_notification\recipient;

use \totara_notification\recipient\recipient;

class authors implements recipient {
    
    /**
     * Label to show in management interface
     * @return string
     */
    public static function get_name(): string {
        return get_string('authors', 'your_component');
    }

    /**
     * Get list of relevant recipient user_id's
     * @return int[]
     */
    public static function get_user_ids(array $data) {
        return \your_component\component::get_authors($data['some_data_id']);
    }
}


Once this recipient is linked to a specific notifiable event the notifiable event's resolver will execute the recipients 'get_user_ids' static function of this recipient class and pass the relevant data to it. The data that is passed to 'get_user_ids' is setup by the notifiable event's resolver and also has access to the event's data:

namespace totara_comment\totara_notification\resolver;

class comment_created extends notifiable_event_resolver {

	/**
     * Get recipients for this notifiable event.
     * @return array
     */
	public function get_recipient_ids(string $recipient): array {
		$comment = comment::from_id($this->event_data['comment_id']);
		$data = [
            'object_id' => $this->event_data['comment_id'],
            'component' => $comment->get_component(),
            'area' => $comment->get_area(),
            'instance_id' => $comment->get_instanceid(),
        ];

        /** @var recipient $recipient */
        return $recipient::get_user_ids($data);
	}

}


List your recipient in relevant \totara_notification\event\notifiable_event_resolver::get_notification_available_recipients().

namespace your_component\event;

use core\event\base;
use totara_notification\event\notifiable_event;
use your_component\totara_notification\recipient\{authors, commenters};

final class something_happened extends base implements notifiable_event {
// ...
    public static function get_notification_available_recipients(): array {
        return [authors::class];
    }
// ...
}


Optionally, make it default in your built-in notification.

namespace your_component\totara_notification\notification;

use your_component\event\something_happened;
use totara_notification\notification\built_in_notification;
use your_component\totara_notification\recipient\authors;

final class something_happened_notification extends built_in_notification {
    /**
     * Link to notifiable_event this notification responds to
     * @return string
     */
    public static function get_event_class_name(): string {
        return something_happened::class;
    }

    /**
     * Default recipient class name
     * @return string
     */
    public static function get_recipient_name(): string {
        return authors::class;
    }