From f2778c3158229131580a5e821cb489d056f55d60 Mon Sep 17 00:00:00 2001 From: Matthew Setter Date: Wed, 18 Dec 2019 13:02:24 +0100 Subject: [PATCH 1/4] Migrate the Notifications API documentation to the docs This change ports the Markdown-formatted content in the Notifications app's docs directory to the developer documentation, migrating it to AsciiDoc format in the process. It also enhances the formatting, refines the wording, and makes several other improvements to enhance readability. --- .../delete-user-notification-response.json | 14 + .../get-server-capabilities-response.json | 15 + .../get-server-capabilities-response.xml | 16 ++ ...tifications-no-notifications-response.json | 12 + .../get-user-notifications-response.json | 31 ++ .../notifications/get-server-capabilities.sh | 14 + .../notifications/get-user-notifications.sh | 15 + .../core/apis/ocs/notifications/index.adoc | 6 + .../notifications/notification-workflow.adoc | 162 +++++++++++ .../ocs/notifications/ocs-endpoint-v1.adoc | 266 ++++++++++++++++++ site.yml | 1 + 11 files changed, 552 insertions(+) create mode 100644 modules/developer_manual/examples/core/apis/ocs/notifications/delete-user-notification-response.json create mode 100644 modules/developer_manual/examples/core/apis/ocs/notifications/get-server-capabilities-response.json create mode 100644 modules/developer_manual/examples/core/apis/ocs/notifications/get-server-capabilities-response.xml create mode 100644 modules/developer_manual/examples/core/apis/ocs/notifications/get-user-notifications-no-notifications-response.json create mode 100644 modules/developer_manual/examples/core/apis/ocs/notifications/get-user-notifications-response.json create mode 100644 modules/developer_manual/examples/core/scripts/curl/ocs/notifications/get-server-capabilities.sh create mode 100644 modules/developer_manual/examples/core/scripts/curl/ocs/notifications/get-user-notifications.sh create mode 100644 modules/developer_manual/pages/core/apis/ocs/notifications/index.adoc create mode 100644 modules/developer_manual/pages/core/apis/ocs/notifications/notification-workflow.adoc create mode 100644 modules/developer_manual/pages/core/apis/ocs/notifications/ocs-endpoint-v1.adoc diff --git a/modules/developer_manual/examples/core/apis/ocs/notifications/delete-user-notification-response.json b/modules/developer_manual/examples/core/apis/ocs/notifications/delete-user-notification-response.json new file mode 100644 index 0000000000..2c8bb6ee66 --- /dev/null +++ b/modules/developer_manual/examples/core/apis/ocs/notifications/delete-user-notification-response.json @@ -0,0 +1,14 @@ +{ + "ocs": { + ... + "data": { + ... + "capabilities": { + ... + "notifications": { + "ocs-endpoints": ["list", "get", "delete"] + } + } + } + } +} diff --git a/modules/developer_manual/examples/core/apis/ocs/notifications/get-server-capabilities-response.json b/modules/developer_manual/examples/core/apis/ocs/notifications/get-server-capabilities-response.json new file mode 100644 index 0000000000..cf2b51f433 --- /dev/null +++ b/modules/developer_manual/examples/core/apis/ocs/notifications/get-server-capabilities-response.json @@ -0,0 +1,15 @@ +{ + "ocs": { + "data": { + "capabilities": { + "notifications": { + "ocs-endpoints": [ + "list", + "get", + "delete" + ] + } + } + } + } +} diff --git a/modules/developer_manual/examples/core/apis/ocs/notifications/get-server-capabilities-response.xml b/modules/developer_manual/examples/core/apis/ocs/notifications/get-server-capabilities-response.xml new file mode 100644 index 0000000000..5f9518483e --- /dev/null +++ b/modules/developer_manual/examples/core/apis/ocs/notifications/get-server-capabilities-response.xml @@ -0,0 +1,16 @@ + + + + + + + + + list + get + delete + + + + + diff --git a/modules/developer_manual/examples/core/apis/ocs/notifications/get-user-notifications-no-notifications-response.json b/modules/developer_manual/examples/core/apis/ocs/notifications/get-user-notifications-no-notifications-response.json new file mode 100644 index 0000000000..05317fda46 --- /dev/null +++ b/modules/developer_manual/examples/core/apis/ocs/notifications/get-user-notifications-no-notifications-response.json @@ -0,0 +1,12 @@ +{ + "ocs": { + "meta": { + "status": "ok", + "statuscode": 200, + "message": null, + "totalitems": "", + "itemsperpage": "" + }, + "data": [] + } +} diff --git a/modules/developer_manual/examples/core/apis/ocs/notifications/get-user-notifications-response.json b/modules/developer_manual/examples/core/apis/ocs/notifications/get-user-notifications-response.json new file mode 100644 index 0000000000..7c2ee8aa9f --- /dev/null +++ b/modules/developer_manual/examples/core/apis/ocs/notifications/get-user-notifications-response.json @@ -0,0 +1,31 @@ +{ + "ocs": { + "meta": { + "status": "ok", + "statuscode": 200, + "message": null + }, + "data": [{ + "notification_id": 61, + "app": "files_sharing", + "user": "admin", + "datetime": "2004-02-12T15:19:21+00:00", + "object_type": "remote_share", + "object_id": "13", + "subject": "You received admin@localhost as a remote share from test", + "message": "", + "link": "http://localhost/index.php/apps/files_sharing/pending", + "actions": [{ + "label": "Accept", + "link": "http:\/\/localhost\/ocs\/v1.php\/apps\/files_sharing\/api\/v1\/remote_shares\/13", + "type": "POST", + "primary": true + }, { + "label": "Decline", + "link": "http:\/\/localhost\/ocs\/v1.php\/apps\/files_sharing\/api\/v1\/remote_shares\/13", + "type": "DELETE", + "primary": false + }] + }] + } +} diff --git a/modules/developer_manual/examples/core/scripts/curl/ocs/notifications/get-server-capabilities.sh b/modules/developer_manual/examples/core/scripts/curl/ocs/notifications/get-server-capabilities.sh new file mode 100644 index 0000000000..929a97a00e --- /dev/null +++ b/modules/developer_manual/examples/core/scripts/curl/ocs/notifications/get-server-capabilities.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +USERNAME=admin +PASSWORD={oc-examples-password} +API_PATH="ocs/v2.php/cloud/capabilities" +SERVER_URI="{oc-examples-server-url}" + +# Get server capabilities in XML format +curl '$SERVER_URI/$API_PATH/' \ + --user "${USERNAME}:${PASSWORD}" + +# Get server capabilities in JSON format +curl '$SERVER_URI/$API_PATH?format=json' \ + --user "${USERNAME}:${PASSWORD}" | jq diff --git a/modules/developer_manual/examples/core/scripts/curl/ocs/notifications/get-user-notifications.sh b/modules/developer_manual/examples/core/scripts/curl/ocs/notifications/get-user-notifications.sh new file mode 100644 index 0000000000..70c0034609 --- /dev/null +++ b/modules/developer_manual/examples/core/scripts/curl/ocs/notifications/get-user-notifications.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +USERNAME=admin +PASSWORD={oc-examples-password} +API_PATH="ocs/v2.php/apps/notifications/api/v1/notifications" +SERVER_URI="{oc-examples-server-url}" + +# Get response in XML format +curl '$SERVER_URI/$API_PATH/' \ + --user "${USERNAME}:${PASSWORD}" + +# Get response in JSON format +curl '$SERVER_URI/$API_PATH?format=json' \ + --user "${USERNAME}:${PASSWORD}" | jq + diff --git a/modules/developer_manual/pages/core/apis/ocs/notifications/index.adoc b/modules/developer_manual/pages/core/apis/ocs/notifications/index.adoc new file mode 100644 index 0000000000..ccc6314b88 --- /dev/null +++ b/modules/developer_manual/pages/core/apis/ocs/notifications/index.adoc @@ -0,0 +1,6 @@ += Notifications API + +In this section you will information on ownCloud’s Notifications API, including: + +* xref:core/apis/ocs/notifications/notification-workflow.adoc[The notification workflow] +* xref:core/apis/ocs/notifications/ocs-endpoint-v1.adoc[The OCS API Endpoint (v1)] diff --git a/modules/developer_manual/pages/core/apis/ocs/notifications/notification-workflow.adoc b/modules/developer_manual/pages/core/apis/ocs/notifications/notification-workflow.adoc new file mode 100644 index 0000000000..1bbae01740 --- /dev/null +++ b/modules/developer_manual/pages/core/apis/ocs/notifications/notification-workflow.adoc @@ -0,0 +1,162 @@ += Notification Workflow for an App that sends Notifications + +== Example story + +Let's assume the following example scenario. +Our app is the files_sharing app. +We want to notify the user when a remote share has to be accepted/declined. +If the user has dealt with it, we want to remove the notification again. + +=== Creating a New Notification + +. Grab a new notification object (`\OCP\Notification\INotification`) from the manager (`\OCP\Notification\IManager`): ++ +[source,php] +---- +getNotificationManager(); +$notification = $manager->createNotification(); +---- + +. Set the necessary information for the notification: ++ +[source,php] +---- +createAction(); +$acceptAction + ->setLabel('accept') + ->setLink('/apps/files_sharing/api/v1/remote_shares/1337', 'POST'); + +$declineAction = $notification->createAction(); +$declineAction->setLabel('decline') + ->setLink('/apps/files_sharing/api/v1/remote_shares/1337', 'DELETE'); + +$notification->setApp('files_sharing') + ->setUser('recipient1') + ->setDateTime(new DateTime()) + ->setObject('remote', '1337') // $type and $id + ->setSubject('remote_share', ['/fancyFolder']) // $subject and $parameters + ->addAction($acceptAction) + ->addAction($declineAction) +; +---- ++ +Setting *app, user, timestamp, object and subject* are mandatory. +You should not use a translated subject, message or action label. +Use something like a "language key", to avoid length problems with translations in the storage of a notification app. +Translation is done via invocation of your notifier by the manager when the notification is prepared for display. + +. Send the notification back to the manager: `$manager->notify($notification);` + +=== Preparing a Notification for Display + +. In `app.php`, register your Notifier (`\OCP\Notification\INotifier`) interface to the manager, using a `\Closure`: ++ +[source,php] +---- +getNotificationManager(); +$manager->registerNotifier(function() { + return new \OCA\Files_Sharing\Notifier(\OC::$server->getL10NFactory()); +}); +---- +. The manager will execute the closure and then call the `prepare()` method on your notifier. +If the notification is not known by your app, just throw an `\InvalidArgumentException`, but if it is actually from your app, you must set the parsed subject, message and action labels: ++ +[source,php] +---- +factory = $factory; +} + +/** + * @param INotification $notification + * @param string $languageCode The code of the language that should be used to prepare the notification + */ +public function prepare(INotification $notification, $languageCode) { + if ($notification->getApp() !== 'files_sharing') { + // Not my app => throw + throw new \InvalidArgumentException(); + } + + // Read the language from the notification + $l = $this->factory->get('myapp', $languageCode); + + switch ($notification->getSubject()) { + // Deal with known subjects + case 'remote_share': + $notification->setParsedSubject( + (string) $l->t( + 'You received the remote share "%s"', + $notification->getSubjectParameters() + ) + ); + + // Deal with the actions for a known subject + foreach ($notification->getActions() as $action) { + switch ($action->getLabel()) { + case 'accept': + $action->setParsedLabel( + (string) $l->t('Accept') + ); + break; + + case 'decline': + $action->setParsedLabel( + (string) $l->t('Decline') + ); + break; + } + + $notification->addParsedAction($action); + } + return $notification; + break; + + default: + // Unknown subject => Unknown notification => throw + throw new \InvalidArgumentException(); + } +} +---- + +NOTE: Currently, no markup is allowed. + +=== Marking a Notification as Read/Deleted/Processed/Obsoleted + +If the user accepted the share or the share was removed/unshared, we want to remove the notification, because no user action is needed anymore. +To do this, we simply have to call the `markProcessed()` method on the manager with the neccessary information on a notification object: + +[source,php] +---- +getNotificationManager(); +$notification + ->setApp('files_sharing') + ->setObject('remote', 1337) + ->setUser('recipient1'); +$manager->markProcessed($notification); +---- + +Only the app name is mandatory: so if you don't set the user, the notification will be marked as processed for all users that have it. +So the following example will remove all notifications for the app files_sharing on the object "_remote #1337_": + +[source,php] +---- +getNotificationManager(); +$notification + ->setApp('files_sharing') + ->setObject('remote', 1337); +$manager->markProcessed($notification); +---- diff --git a/modules/developer_manual/pages/core/apis/ocs/notifications/ocs-endpoint-v1.adoc b/modules/developer_manual/pages/core/apis/ocs/notifications/ocs-endpoint-v1.adoc new file mode 100644 index 0000000000..a746695b3f --- /dev/null +++ b/modules/developer_manual/pages/core/apis/ocs/notifications/ocs-endpoint-v1.adoc @@ -0,0 +1,266 @@ += OCS Notifications API +:toc: right +:toclevels: 1 +:request-base-path: ocs/v2.php + +== Prerequisites + +This API requires {2fa-app-url}[the 2-Factor Authentication app] to be installed and enabled. + +== Check Server Capabilities + +In order to find out if notifications is installed and enabled on the server, you can run a request against the capabilities endpoint. + +* Path: `{request-base-path}/cloud/capabilities` +* Method: `GET` + +=== Request Parameters + +[cols="15%,15%,70%",options="header",width=100%] +|=== +|Attribute +|Type +|Description + +|`format` +|string +|The format to return the response in. +It can be either `XML` or `JSON`. +|=== + +=== Returns + +On success, the request returns either an XML (the default) or a JSON response, along with an `HTTP 200 OK` status code, which shows the server’s notifications capabilities. + +=== Example Responses + +[tabs] +==== +JSON:: ++ +-- +[source,json] +---- +include::{examplesdir}core/apis/ocs/notifications/get-server-capabilities-response.json[] +---- +-- + +XML:: ++ +-- +[source,xml] +---- +include::{examplesdir}core/apis/ocs/notifications/get-server-capabilities-response.xml[] +---- +-- +==== + +=== Code Example + +[tabs] +==== +Curl:: ++ +-- +[source,bash] +---- +include::{examplesdir}core/scripts/curl/ocs/notifications/get-server-capabilities.sh[] +---- +-- +==== + +== Get User Notifications + +This endpoint supports retrieving a list of notifications for a user. + +* Path: `{request-base-path}/apps/notifications/api/v1/notifications` +* Method: `GET` + +[TIP] +==== +In order to get a single notification, you can send a `GET` request against the endpoint below. +Note the {id} property at the end of the endpoint. + +[source,console] +---- +{request-base-path}/apps/notifications/api/v1/notifications/{id} +---- +==== + +=== Request Parameters + +[cols="15%,15%,70%",options="header",width=100%] +|=== +|Attribute +|Type +|Description + +|`format` +|string +|The format to return the response in. +It can be either `XML` or `JSON`. +|=== + +=== Returns + +On success, the request returns either an XML (the default) or a JSON response, along with an `HTTP 200 OK` status code, which shows the server’s notifications capabilities. + +=== Example Responses + +==== Response With Notifications + +[tabs] +==== +JSON:: ++ +-- +[source,json] +---- +include::{examplesdir}core/apis/ocs/notifications/get-user-notifications-response.json[] +---- +-- +==== + +==== Response Without Notifications + +[tabs] +==== +JSON:: ++ +-- +[source,json] +---- +include::{examplesdir}core/apis/ocs/notifications/get-user-notifications-no-notifications-response.json[] +---- +-- +==== + +=== Specification + +Optional elements are still set in the array, the value is just empty: + +[options="header"] +|=== +|Type | Empty value +|array | `[]` +|string | `""` +|=== + +==== Notification Element + +[cols="20%,10%,70%",options="header"] +|=== +|Field name +|Type +|Value description + +|`actions` +|array +|(Optional) An array of action elements. + +|`app` +|string +|The name of the app that triggered the notification. + +|`datetime` +|string +|The ISO 8601 date and time of when the notification was published. + +|`link` +|string +|(Optional) A link that should be followed when the subject/message is clicked. + +|`message` +|string +|(Optional) The translated, potentially longer, message that should be presented to the user. + +|`notification_id` +|int +|The unique notification identifier. +It can be used to dismiss a notification. + +|`object_id` +|string +|The ID of the object which the notification is about. +The id can be used in PHP to mark a notification as resolved. + +|`object_type` +|string +|The type of the object which the notification is about. +It can be used in PHP to mark a notification as resolved. + +|`subject` +|string +|The translated short subject that should be presented to the user. + +|`user` +|string +|The user id of the user that receives the notification. +|=== + +==== Action Element + +[cols="20%,10%,70%",options="header"] +|=== +|Field name +|Type +|Value description + +|`label` +|string +|The translated short label of the action/button that should be presented to the user. + +|`link` +|string +|A link that should be followed when the action is performed/clicked. + +|`primary` +|bool +|If the action is the primary action for the notification or not. + +|`type` +|string +|The HTTP method that should be used for the request against the link. +It can be one of `GET`, `POST`, or `DELETE`. +|=== + +=== Code Example + +[tabs] +==== +Curl:: ++ +-- +[source,bash] +---- +include::{examplesdir}core/scripts/curl/ocs/notifications/get-user-notifications.sh[] +---- +-- +==== + +NOTE: If the HTTP status code is `204` (No Content), you can slow down the polling to once per hour. +This status code means that there is no app that can generate notifications. + +== Delete a User Notification + +To delete a notification, send a `DELETE` request against `{request-base-path}/apps/notifications/api/v1/notifications/{id}` + +* Path: `{request-base-path}/apps/notifications/api/v1/notifications/{id}` +* Method: `DELETE` + +=== Request Parameters + +[cols="15%,15%,70%",options="header",width=100%] +|=== +|Attribute +|Type +|Description + +|`id` +|integer +|The id of the notification to delete. +|=== + +=== Returns + +On success, the request returns either an {http-status-codes-base-url}/100[HTTP 100 Continue] status code, and no response body. diff --git a/site.yml b/site.yml index d66ea334b2..4fc40f1054 100644 --- a/site.yml +++ b/site.yml @@ -60,6 +60,7 @@ asciidoc: occ-command-example-prefix: 'sudo -u www-data php occ' occ-command-example-prefix-no-sudo: 'php occ' php-supported-versions-url: https://secure.php.net/supported-versions.php + http-status-codes-base-url: https://developer.mozilla.org/en-US/docs/Web/Status recommended-php-version: 7.3 std-port-http: 8080 std-port-memcache: 11211 From 46a00142e0632c873eb25a5e63258113980b59e0 Mon Sep 17 00:00:00 2001 From: Matthew Setter Date: Wed, 18 Dec 2019 14:45:53 +0100 Subject: [PATCH 2/4] Integrate Notifications Workflow into the existing Notifications docs It seemed to make most sense to integrate the content into the existing notifications docs (under app/advanced) rather than make it a part of OCS API documentation. --- .../pages/app/advanced/notifications.adoc | 187 +++++++++++++++++- .../notifications/notification-workflow.adoc | 162 --------------- 2 files changed, 185 insertions(+), 164 deletions(-) delete mode 100644 modules/developer_manual/pages/core/apis/ocs/notifications/notification-workflow.adoc diff --git a/modules/developer_manual/pages/app/advanced/notifications.adoc b/modules/developer_manual/pages/app/advanced/notifications.adoc index efadc091d5..775243fdaf 100644 --- a/modules/developer_manual/pages/app/advanced/notifications.adoc +++ b/modules/developer_manual/pages/app/advanced/notifications.adoc @@ -1,8 +1,191 @@ = Notifications -In this document, you can learn how to send notifications in apps. +In this document, you can learn how to: -== Sending Notifications +* xref:create-a-new-notification[Create a notification] +* xref:mark-a-notification[Mark a notification] +* xref:prepare-a-notification-for-display[Prepare a notification for display] +* xref:send-notifications[Send notifications] + +== Create a New Notification + +To create a new notification requires the following steps: + +. xref:retrieve-new-notification-object[Retrieve a new notification object from the notification manager] +. xref:set-the-necessary-information-for-the-notification[Set the necessary notification information] +. xref:send-the-notification-back-to-the-manager[Send the notification back to the manager] + +[[retrieve-new-notification-object]] +=== Retrieve a New Notification Object From the Notification Manager + +Grab a new notification object (`\OCP\Notification\INotification`) from the manager (`\OCP\Notification\IManager`). + +[source,php] +---- +getNotificationManager(); +$notification = $manager->createNotification(); +---- + +=== Set the Necessary Information for the Notification + +[source,php] +---- +createAction(); +$acceptAction + ->setLabel('accept') + ->setLink('/apps/files_sharing/api/v1/remote_shares/1337', 'POST'); + +$declineAction = $notification->createAction(); +$declineAction->setLabel('decline') + ->setLink('/apps/files_sharing/api/v1/remote_shares/1337', 'DELETE'); + +$notification->setApp('files_sharing') + ->setUser('recipient1') + ->setDateTime(new DateTime()) + ->setObject('remote', '1337') // $type and $id + ->setSubject('remote_share', ['/fancyFolder']) // $subject and $parameters + ->addAction($acceptAction) + ->addAction($declineAction) +; +---- + +TIP: Setting _app_, _user_, _timestamp_, _object_ and _subject_ are mandatory. + +You should not use a translated _subject_, _message_ or _action label_. +Use something like a "_language key_", to avoid length problems with translations in the storage of a notification app. +Translation is done via invocation of your notifier by the manager when the notification is prepared for display. + +=== Send the Notification Back to the Manager + +[source,php] +---- +notify($notification); + +---- +== Mark a Notification + +If the user accepted the share or the share was removed/unshared, we want to remove the notification, because no user action is needed anymore. +To do this, we simply have to call the `markProcessed()` method on the manager with the necessary information on a notification object: + +[source,php] +---- +getNotificationManager(); +$notification + ->setApp('files_sharing') + ->setObject('remote', 1337) + ->setUser('recipient1'); +$manager->markProcessed($notification); +---- + +Only the app name is mandatory, so if you don't set the user, the notification will be marked as processed for all users that have it. + +The following example shows how to mark all notifications for the `files_sharing` app on the object "_remote #1337_" as processed. + +[source,php] +---- +getNotificationManager(); +$notification + ->setApp('files_sharing') + ->setObject('remote', 1337); +$manager->markProcessed($notification); +---- + +Notifications can be marked as _read_, _deleted_, _processed_, or _obsoleted_. +To + + +== Prepare a Notification for Display + +To prepare a notification for display, in `app.php`, register your Notifier (`\OCP\Notification\INotifier`) interface to the manager, using a `\Closure`. + +[source,php] +---- +getNotificationManager(); +$manager->registerNotifier(function() { + return new \OCA\Files_Sharing\Notifier(\OC::$server->getL10NFactory()); +}); +---- + +The manager will execute the closure and then call the `prepare()` method on your notifier. +If the notification is not known by your app, throw an `\InvalidArgumentException`. +However, if it is actually from your app, you must set the parsed _subject_, _message_, and _action_ labels. + +[source,php] +---- +factory = $factory; +} + +/** + * @param INotification $notification + * @param string $languageCode The code of the language that should be used to prepare the notification + */ +public function prepare(INotification $notification, $languageCode) { + if ($notification->getApp() !== 'files_sharing') { + // Not my app => throw + throw new \InvalidArgumentException(); + } + + // Read the language from the notification + $l = $this->factory->get('myapp', $languageCode); + + switch ($notification->getSubject()) { + // Deal with known subjects + case 'remote_share': + $notification->setParsedSubject( + (string) $l->t( + 'You received the remote share "%s"', + $notification->getSubjectParameters() + ) + ); + + // Deal with the actions for a known subject + foreach ($notification->getActions() as $action) { + switch ($action->getLabel()) { + case 'accept': + $action->setParsedLabel( + (string) $l->t('Accept') + ); + break; + + case 'decline': + $action->setParsedLabel( + (string) $l->t('Decline') + ); + break; + } + + $notification->addParsedAction($action); + } + return $notification; + break; + + default: + // Unknown subject => Unknown notification => throw + throw new \InvalidArgumentException(); + } +} +---- + +NOTE: Currently, no markup is allowed. + +== Send Notifications To send notifications from your app, requires four steps, these are: diff --git a/modules/developer_manual/pages/core/apis/ocs/notifications/notification-workflow.adoc b/modules/developer_manual/pages/core/apis/ocs/notifications/notification-workflow.adoc deleted file mode 100644 index 1bbae01740..0000000000 --- a/modules/developer_manual/pages/core/apis/ocs/notifications/notification-workflow.adoc +++ /dev/null @@ -1,162 +0,0 @@ -= Notification Workflow for an App that sends Notifications - -== Example story - -Let's assume the following example scenario. -Our app is the files_sharing app. -We want to notify the user when a remote share has to be accepted/declined. -If the user has dealt with it, we want to remove the notification again. - -=== Creating a New Notification - -. Grab a new notification object (`\OCP\Notification\INotification`) from the manager (`\OCP\Notification\IManager`): -+ -[source,php] ----- -getNotificationManager(); -$notification = $manager->createNotification(); ----- - -. Set the necessary information for the notification: -+ -[source,php] ----- -createAction(); -$acceptAction - ->setLabel('accept') - ->setLink('/apps/files_sharing/api/v1/remote_shares/1337', 'POST'); - -$declineAction = $notification->createAction(); -$declineAction->setLabel('decline') - ->setLink('/apps/files_sharing/api/v1/remote_shares/1337', 'DELETE'); - -$notification->setApp('files_sharing') - ->setUser('recipient1') - ->setDateTime(new DateTime()) - ->setObject('remote', '1337') // $type and $id - ->setSubject('remote_share', ['/fancyFolder']) // $subject and $parameters - ->addAction($acceptAction) - ->addAction($declineAction) -; ----- -+ -Setting *app, user, timestamp, object and subject* are mandatory. -You should not use a translated subject, message or action label. -Use something like a "language key", to avoid length problems with translations in the storage of a notification app. -Translation is done via invocation of your notifier by the manager when the notification is prepared for display. - -. Send the notification back to the manager: `$manager->notify($notification);` - -=== Preparing a Notification for Display - -. In `app.php`, register your Notifier (`\OCP\Notification\INotifier`) interface to the manager, using a `\Closure`: -+ -[source,php] ----- -getNotificationManager(); -$manager->registerNotifier(function() { - return new \OCA\Files_Sharing\Notifier(\OC::$server->getL10NFactory()); -}); ----- -. The manager will execute the closure and then call the `prepare()` method on your notifier. -If the notification is not known by your app, just throw an `\InvalidArgumentException`, but if it is actually from your app, you must set the parsed subject, message and action labels: -+ -[source,php] ----- -factory = $factory; -} - -/** - * @param INotification $notification - * @param string $languageCode The code of the language that should be used to prepare the notification - */ -public function prepare(INotification $notification, $languageCode) { - if ($notification->getApp() !== 'files_sharing') { - // Not my app => throw - throw new \InvalidArgumentException(); - } - - // Read the language from the notification - $l = $this->factory->get('myapp', $languageCode); - - switch ($notification->getSubject()) { - // Deal with known subjects - case 'remote_share': - $notification->setParsedSubject( - (string) $l->t( - 'You received the remote share "%s"', - $notification->getSubjectParameters() - ) - ); - - // Deal with the actions for a known subject - foreach ($notification->getActions() as $action) { - switch ($action->getLabel()) { - case 'accept': - $action->setParsedLabel( - (string) $l->t('Accept') - ); - break; - - case 'decline': - $action->setParsedLabel( - (string) $l->t('Decline') - ); - break; - } - - $notification->addParsedAction($action); - } - return $notification; - break; - - default: - // Unknown subject => Unknown notification => throw - throw new \InvalidArgumentException(); - } -} ----- - -NOTE: Currently, no markup is allowed. - -=== Marking a Notification as Read/Deleted/Processed/Obsoleted - -If the user accepted the share or the share was removed/unshared, we want to remove the notification, because no user action is needed anymore. -To do this, we simply have to call the `markProcessed()` method on the manager with the neccessary information on a notification object: - -[source,php] ----- -getNotificationManager(); -$notification - ->setApp('files_sharing') - ->setObject('remote', 1337) - ->setUser('recipient1'); -$manager->markProcessed($notification); ----- - -Only the app name is mandatory: so if you don't set the user, the notification will be marked as processed for all users that have it. -So the following example will remove all notifications for the app files_sharing on the object "_remote #1337_": - -[source,php] ----- -getNotificationManager(); -$notification - ->setApp('files_sharing') - ->setObject('remote', 1337); -$manager->markProcessed($notification); ----- From 18f3c5384ea5f84eefcc2e70de1e77a976c445fe Mon Sep 17 00:00:00 2001 From: Matthew Setter Date: Wed, 18 Dec 2019 14:57:38 +0100 Subject: [PATCH 3/4] Update the navigation to reflect the updated content structure --- modules/developer_manual/nav.adoc | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/developer_manual/nav.adoc b/modules/developer_manual/nav.adoc index bf8471876f..1ab7f7439a 100644 --- a/modules/developer_manual/nav.adoc +++ b/modules/developer_manual/nav.adoc @@ -22,6 +22,7 @@ *** xref:core/apis/index.adoc[Available APIs] **** xref:core/apis/externalapi.adoc[The External API] **** OCS +***** xref:core/apis/ocs/notifications/ocs-endpoint-v1.adoc[The OCS Notifications API (v1)] ***** xref:core/apis/ocs-capabilities.adoc[The OCS REST API] ***** xref:core/apis/ocs-recipient-api.adoc[The OCS Recipient API] ***** xref:core/apis/ocs-share-api.adoc[The OCS Share API] From 7337113511c9b1c19c6e9de5912f525eb530fd7b Mon Sep 17 00:00:00 2001 From: Matthew Setter Date: Wed, 18 Dec 2019 14:58:03 +0100 Subject: [PATCH 4/4] Update the notifications api documentation --- .../pages/core/apis/ocs/notifications/ocs-endpoint-v1.adoc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/developer_manual/pages/core/apis/ocs/notifications/ocs-endpoint-v1.adoc b/modules/developer_manual/pages/core/apis/ocs/notifications/ocs-endpoint-v1.adoc index a746695b3f..2baa66fe83 100644 --- a/modules/developer_manual/pages/core/apis/ocs/notifications/ocs-endpoint-v1.adoc +++ b/modules/developer_manual/pages/core/apis/ocs/notifications/ocs-endpoint-v1.adoc @@ -1,7 +1,8 @@ -= OCS Notifications API += OCS Notifications API (v1) :toc: right :toclevels: 1 :request-base-path: ocs/v2.php +:2fa-app-url: https://github.com/owncloud/twofactor_totp == Prerequisites