Repository navigation
Channels
A channel is a named topic that notifications are sent on, for example "plugin updates" or "new comments". Channels are what the plugin is organised around. The channel registry, the notifications_messages table and the notifications_subscriptions table are all keyed on the channel name. See Database Schema.
Status: Registering and listing channels works on the
developbranch. Sending notifications on a channel, choosing who receives them, and managing subscriptions are planned for 0.3.0 and are not built yet. Each section below is marked Built or Planned. The planned design comes from the 0.3.0 release plan.
Terminology: The older Requirements (v1) page uses "channel" to mean the delivery method (admin bar, email, mobile app). In the current design a channel is the topic of a notification. Where a notification is shown is set by its
context, for exampleadminbar.
Plugin / core Channel registry Database
+-----------------+ +------------------+
| register_channel|--------->| my-plugin/foo |
+-----------------+ | core/updates ... |
+------------------+
+-----------------+ look up |
| notify(channel) |------------------+
+-----------------+ |
| resolve recipients v
| (explicit, or channel subscribers +------------------------+
| minus snoozed) | notifications_messages | one row per notification
+------------------------------------->| notifications_queue | one row per recipient
+------------------------+
|
REST API <-------------------+
(admin bar, filtered by channel_name, context)
Register channels on the init hook with WP\Notifications\register_channel(), defined in includes/channels.php:
add_action( 'init', function () {
WP\Notifications\register_channel(
'my-plugin/order-shipped',
array(
'title' => __( 'Order Shipped', 'my-plugin' ),
'description' => __( 'Order shipping events.', 'my-plugin' ),
'icon' => 'cart',
'context' => 'adminbar',
)
);
} );| Argument | Required | Description |
|---|---|---|
title |
Yes | Human-readable title of the channel, shown to users. |
description |
No | Description of the events the channel covers. |
icon |
No | Icon for the channel. |
context |
No | Where notifications from this channel are displayed. |
register_channel() returns the WP\Notifications\Model\Channel object, or false on failure. You can also pass a Model\Channel instance instead of a name and arguments.
To remove a channel, call WP\Notifications\unregister_channel( 'my-plugin/order-shipped' ). It returns the removed channel, or false if that name wasn't registered.
Channel names must:
- be strings
- contain no uppercase characters
- match
namespace/name, using only lowercase letters, digits and hyphens (/^[a-z0-9-]+\/[a-z0-9-]+$/) - not already be registered
A name that breaks these rules triggers _doing_it_wrong(), and registration returns false.
Use your plugin or theme slug as the namespace. The core namespace is reserved for channels the plugin registers itself.
WP\Notifications\Channel_Registry (includes/class-channel-registry.php) is a single shared instance, like the block type registry. It lives only in memory for the current request, so channels must be registered on every request and are never written to the database. The database stores only the channel name.
| Method | Description |
|---|---|
Channel_Registry::get_instance() |
Get the registry. |
register( $name, $args ) |
Register a channel. |
unregister( $name ) |
Unregister a channel. |
get_registered( $name ) |
Get one channel, or null if it isn't registered. |
get_all_registered() |
Get all registered channels, keyed by name. |
is_registered( $name ) |
Check whether a channel is registered. |
The plugin registers these channels on init. Nothing sends notifications on them yet, because nothing is hooked to the matching WordPress events.
| Channel | Title |
|---|---|
core/updates |
WordPress Updates |
core/plugin-install |
Plugin Install |
core/plugin-uninstall |
Plugin Uninstall |
core/plugin-activate |
Plugin Activate |
core/plugin-deactivate |
Plugin Deactivate |
core/plugin-updates |
Plugin Update |
core/post-new |
New Post |
core/post-edit |
Edit Post |
core/post-delete |
Delete Post |
core/comment-new |
New Comment |
GET /wp-notifications/v1/channels returns every registered channel. Each item has name, title, description, icon and context. It is meant to feed a settings screen where users choose which channels they want to hear about.
The endpoint does not filter channels by permission yet.
A new notify() function will send a notification on a channel, with $channel->emit() as a shorthand that calls it:
WP\Notifications\notify(
'my-plugin/order-shipped',
array(
'title' => __( 'Order #123 shipped', 'my-plugin' ),
'message' => __( 'The order is on its way.', 'my-plugin' ),
'severity' => 'info',
)
); // Returns the message ID, or a WP_Error.The planned flow:
- Look the channel up in the registry. If it isn't registered, return a
WP_Error. This guarantees that only registered channel names reach thechannel_namecolumn. - Require a non-empty
message, and build the message. - Work out who receives it (see below).
- Save one row to
notifications_messagesand one row per recipient tonotifications_queue. - Fire the
wp_notifications_notifiedaction.
notify() will not check the caller's capabilities. Code running inside WordPress already has full database access, so permissions are checked at the REST API boundary instead.
Recipients are resolved in this order:
- If the
notify()call gives explicitrecipients(user IDs and/or role slugs), use them. - Otherwise, use the users subscribed to the channel, leaving out anyone whose
snoozed_untilis still in the future. -
MVP rule: if the channel has no subscribers, every user with the
read_notificationscapability receives it. - Finally, the
wp_notifications_recipientsfilter can change the list.
Because of rule 3, in 0.3.0 subscriptions can only snooze a channel. Users receive notifications without subscribing first. Changing this later so that no subscribers means no recipients would break existing behaviour.
A subscription is a row in notifications_subscriptions that links a user to a channel by user_id and channel_name, with an optional snoozed_until time.
The planned REST routes are:
| Route | Methods | Purpose |
|---|---|---|
/wp-notifications/v1/subscriptions |
GET |
List the current user's subscriptions. |
/wp-notifications/v1/subscriptions/{namespace}/{name} |
GET, PUT/PATCH, DELETE
|
Read, subscribe to or snooze, and unsubscribe from one channel. |
Today GET /wp-notifications/v1/subscriptions returns an empty list.
Each notification has a context (default adminbar) that says where it appears. When listing notifications over REST, clients will be able to filter by channel_name and context. The channel_name column is indexed for this.
-
Channel titles are copied into every message. Each message row stores the channel title twice: in the
channel_titlecolumn and in themetaJSON. If a plugin later changes a channel's title, older messages keep the old one. The 0.3.0 plan drops this copy (#372). -
Name length isn't limited. The
channel_namecolumn isVARCHAR(50), but registration doesn't check name length. A longer name passes registration and then fails or gets cut off when saved. The 0.3.0 plan widens the column toVARCHAR(64)in both tables. A matching length check in the registry would close the gap. - Subscription permissions. The permission check on the subscriptions REST endpoint is commented out, so logged-out users can call it. This is harmless today only because the endpoint returns nothing.