', {
+ 'class' : 'notification-controls controls-below'
+ });
+
+ var $showMoreButton = $('
', {
+ 'class' : 'notification-showmore',
+ 'text' : t('notifications', 'Show More')
+ });
+
+ $showMoreButton.click(function() {
+ self.removeShowMoreNotificationsButton();
+ self.fetchDescendentV2(nextUrl);
});
- setTimeout(n.close.bind(n), 5000);
+
+ $notificationControlsDiv.append($showMoreButton);
+
+ this.$container.find('div.notification-wrapper').append($notificationControlsDiv);
},
- _shutDownNotifications: function() {
- // The app was disabled or has no notifiers, so we can stop polling
- // And hide the UI as well
- window.clearInterval(this.interval);
- this.$notifications.addClass('hidden');
+ /**
+ * Remove the button created with the "addShowMoreNotificationsButton"
+ */
+ removeShowMoreNotificationsButton: function() {
+ this.$container.find('div.notification-controls.controls-below').remove();
},
/**
- * Adds the notification to the UI
- * @param {OCA.Notifications.Notification} notification
+ * Add a button to the beginning of the notification list to fetch the newer bunch of
+ * notifications. Once the user click in the button, polling will be restarted if the
+ * "fetchAscendentV2" call doesn't return the link to the next call (there aren't any
+ * additional notification available for now)
+ * @param {string} nextUrl the url that will be used for a "fetchAscendentV2" call, that
+ * will be called when the button is clicked. The url should normally be the "next" url
+ * from a result of a previous "fetchAscendentV2" call.
*/
- addToUI: function(notification) {
- $('div.notification-wrapper').prepend(notification.renderElement());
+ addShowNewerNotificationsButton: function(nextUrl) {
+ var self = this;
+ var $notificationControlsDiv = $('', {
+ 'class' : 'notification-controls controls-above'
+ });
+ var $showMoreButton = $('', {
+ 'class' : 'notification-shownewer',
+ 'text' : t('notifications', 'Show Newer Notifications')
+ });
+ $showMoreButton.click(function() {
+ self.removeShowNewerNotificationButton();
+ self.fetchAscendentV2(nextUrl, function(result) {
+ if (typeof result.next === 'undefined') {
+ self.restartPolling();
+ }
+ });
+ });
+
+ $notificationControlsDiv.append($showMoreButton);
+
+ this.$container.find('div.notification-wrapper').prepend($notificationControlsDiv);
+ },
+
+ /**
+ * Remove the button created by "addShowNewerNotificationsButton"
+ */
+ removeShowNewerNotificationButton: function() {
+ this.$container.find('div.notification-controls.controls-above').remove();
},
/**
@@ -298,8 +452,6 @@
.animate({opacity: 1}, 600)
.animate({opacity: 0.7}, 600);
this.$container.find('.emptycontent').addClass('hidden');
-
- this.$notifications.removeClass('hidden');
},
/**
@@ -310,32 +462,6 @@
$('div.notifications-button').removeClass('hasNotifications');
$('div.notifications .emptycontent').removeClass('hidden');
this.$button.find('img').attr('src', OC.imagePath('notifications', 'notifications'));
-
- this.$notifications.addClass('hidden');
- },
-
- /**
- * Performs the AJAX request to retrieve the notifications
- * @param {Function} success
- * @param {Function} failure
- */
- fetch: function(success, failure){
- var self = this;
- var request = $.ajax({
- url: OC.linkToOCS('apps/notifications/api/v1', 2) + 'notifications?format=json',
- type: 'GET'
- });
-
-
- request.done(function(data, statusText, xhr) {
- if (xhr.status === 204 || data.ocs.meta.statuscode === 204) {
- // 204 No Content - Intercept when no notifiers are there.
- self._shutDownNotifications();
- } else {
- success(data.ocs.data, statusText, xhr);
- }
- });
- request.fail(failure);
},
/**
@@ -357,14 +483,6 @@
return this.notifications;
},
- /**
- * Handles the returned data from the AJAX call
- * @param {object} responseData
- */
- parseNotifications: function(responseData) {
-
- },
-
/**
* Returns how many notifications in the UI
*/
diff --git a/lib/Controller/EndpointV2Controller.php b/lib/Controller/EndpointV2Controller.php
new file mode 100644
index 00000000..84d59e07
--- /dev/null
+++ b/lib/Controller/EndpointV2Controller.php
@@ -0,0 +1,286 @@
+
+ *
+ * @copyright Copyright (c) 2018, ownCloud GmbH
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see
+ *
+ */
+namespace OCA\Notifications\Controller;
+
+use OCP\AppFramework\Controller;
+use OCP\AppFramework\Http;
+use OCP\AppFramework\Http\OCSResponse;
+use OCP\IConfig;
+use OCP\IRequest;
+use OCP\IUserSession;
+use OCP\IURLGenerator;
+use OCP\Notification\IManager;
+use OCP\Notification\INotification;
+use OCP\Notification\IAction;
+use OCA\Notifications\Handler;
+
+class EndpointV2Controller extends Controller {
+ /** lists will return a maximum number of 20 results */
+ const ENFORCED_LIST_LIMIT = 20;
+
+ /** @var Handler */
+ private $handler;
+
+ /** @var IManager */
+ private $manager;
+
+ /** @var IUserSession */
+ private $userSession;
+
+ /** @var IConfig */
+ private $config;
+
+ /** @var IURLGenerator */
+ private $urlGenerator;
+
+ public function __construct(Handler $handler, IManager $manager, IUserSession $userSession, IConfig $config, IURLGenerator $urlGenerator, IRequest $request) {
+ parent::__construct('notifications', $request);
+ $this->handler = $handler;
+ $this->manager = $manager;
+ $this->userSession = $userSession;
+ $this->config = $config;
+ $this->urlGenerator = $urlGenerator;
+ }
+
+ /**
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ *
+ * @param int $id the id of the notification
+ * @param string $fetch the fetch order
+ * @param int $limit the limit for the number of notifications to be returned
+ * @param string $format the format of the result: 'json' or 'xml'
+ */
+ public function listNotifications($id = null, $fetch = 'desc', $limit = self::ENFORCED_LIST_LIMIT, $format = 'json') {
+ $userObject = $this->userSession->getUser();
+ if ($userObject === null) {
+ $ocsResponse = new OCSResponse($format, Http::STATUS_FORBIDDEN, null, [], null, null, true);
+ $ocsResponse->setStatus(Http::STATUS_FORBIDDEN);
+ return $ocsResponse;
+ }
+ $userid = $userObject->getUID();
+
+ // if it's "asc" keep it, if not consider it "desc"
+ if (strtoupper($fetch) !== 'ASC') {
+ $order = 'DESC';
+ } else {
+ $order = 'ASC';
+ }
+
+ $maxResults = min(self::ENFORCED_LIST_LIMIT, $limit);
+
+ $language = $this->config->getUserValue($userid, 'core', 'lang', null);
+
+ // fetch the max id before getting the list of notifications
+ $maxId = $this->handler->getMaxNotificationId($userid);
+ if ($maxId === null) {
+ $maxId = -1;
+ }
+
+ if ($order === 'ASC') {
+ // try to get an additional result to check if there is more results available or not
+ $notifications = $this->handler->fetchAscendentList($userid, $id, $maxResults + 1, function (INotification $rawNotification) use ($language) {
+ // we need to prepare the notification in order to decide to discard it or not.
+ // we'll return the prepared notification or null in case of exceptions.
+ return $this->prepareNotification($rawNotification, $language);
+ });
+ } else {
+ $notifications = $this->handler->fetchDescendentList($userid, $id, $maxResults + 1, function (INotification $rawNotification) use ($language) {
+ return $this->prepareNotification($rawNotification, $language);
+ });
+ }
+
+ $data = [];
+ foreach ($notifications as $notificationId => $notification) {
+ $data[] = $this->notificationToArray($notificationId, $notification);
+ }
+
+ if (count($data) > $maxResults) {
+ // make sure we return the number of results specified
+ $data = array_slice($data, 0, $maxResults, true);
+
+ $url = $this->urlGenerator->linkToRoute('notifications.EndpointV2.listNotifications', [
+ 'id' => $data[count($data) - 1]['notification_id'],
+ 'fetch' => strtolower($order),
+ 'limit' => $maxResults,
+ 'format' => $format,
+ ]);
+
+ $ocsResponse = new OCSResponse($format, Http::STATUS_OK, null, [
+ 'notifications' => $data,
+ 'next' => $url,
+ ], null, null, true);
+ } else {
+ $ocsResponse = new OCSResponse($format, Http::STATUS_OK, null, [
+ 'notifications' => $data,
+ ], null, null, true);
+ }
+ $ocsResponse->addHeader('OC-Last-Notification', $maxId);
+ return $ocsResponse;
+ }
+
+ /**
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ *
+ * @param int $id
+ * @param string $format either 'json' or 'xml'
+ * @return Result
+ */
+ public function getNotification($id, $format = 'json') {
+ $userObject = $this->userSession->getUser();
+ if ($userObject === null) {
+ $ocsResponse = new OCSResponse($format, Http::STATUS_FORBIDDEN, null, [], null, null, true);
+ $ocsResponse->setStatus(Http::STATUS_FORBIDDEN);
+ return $ocsResponse;
+ }
+ $userid = $userObject->getUID();
+
+ $notification = $this->handler->getById($id, $userid);
+
+ if (!($notification instanceof INotification)) {
+ $ocsResponse = new OCSResponse($format, Http::STATUS_NOT_FOUND, null, [], null, null, true);
+ $ocsResponse->setStatus(Http::STATUS_NOT_FOUND);
+ return $ocsResponse;
+ }
+
+ $language = $this->config->getUserValue($userid, 'core', 'lang', null);
+
+ try {
+ $notification = $this->manager->prepare($notification, $language);
+ } catch (\InvalidArgumentException $e) {
+ // The app was disabled
+ $ocsResponse = new OCSResponse($format, Http::STATUS_NOT_FOUND, null, [], null, null, true);
+ $ocsResponse->setStatus(Http::STATUS_NOT_FOUND);
+ return $ocsResponse;
+ }
+
+ return new OCSResponse($format, Http::STATUS_OK, null,
+ $this->notificationToArray($id, $notification), null, null, true);
+ }
+
+ /**
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ *
+ * @param int $id
+ * @param string $format either 'json' or 'xml'
+ * @return Result
+ */
+ public function deleteNotification($id, $format = 'json') {
+ $userObject = $this->userSession->getUser();
+ if ($userObject === null) {
+ $ocsResponse = new OCSResponse($format, Http::STATUS_FORBIDDEN, null, [], null, null, true);
+ $ocsResponse->setStatus(Http::STATUS_FORBIDDEN);
+ return $ocsResponse;
+ }
+ $userid = $userObject->getUID();
+
+ $this->handler->deleteById($id, $userid);
+ return new OCSResponse($format, Http::STATUS_OK, null, [], null, null, true);
+ }
+
+
+ /**
+ * @NoAdminRequired
+ * @NoCSRFRequired
+
+ * @param string $format either 'json' or 'xml'
+ */
+ public function getLastNotificationId($format = 'json') {
+ $userObject = $this->userSession->getUser();
+ if ($userObject === null) {
+ $ocsResponse = new OCSResponse($format, Http::STATUS_FORBIDDEN, null, [], null, null, true);
+ $ocsResponse->setStatus(Http::STATUS_FORBIDDEN);
+ return $ocsResponse;
+ }
+ $userid = $userObject->getUID();
+
+
+ $maxId = $this->handler->getMaxNotificationId($userid);
+ if ($maxId === null) {
+ $maxId = -1;
+ }
+
+ $ocsResponse = new OCSResponse($format, Http::STATUS_OK, null, ['id' => $maxId], null, null, true);
+ $ocsResponse->addHeader('OC-Last-Notification', $maxId);
+ return $ocsResponse;
+ }
+
+ /**
+ * @param int $notificationId
+ * @param INotification $notification
+ * @return array
+ */
+ protected function notificationToArray($notificationId, INotification $notification) {
+ $data = [
+ 'notification_id' => $notificationId,
+ 'app' => $notification->getApp(),
+ 'user' => $notification->getUser(),
+ 'datetime' => $notification->getDateTime()->format('c'),
+ 'object_type' => $notification->getObjectType(),
+ 'object_id' => $notification->getObjectId(),
+ 'subject' => $notification->getParsedSubject(),
+ 'message' => $notification->getParsedMessage(),
+ 'link' => $notification->getLink(),
+ 'actions' => [],
+ ];
+ if (method_exists($notification, 'getIcon')) {
+ $data['icon'] = $notification->getIcon();
+ }
+
+ foreach ($notification->getParsedActions() as $action) {
+ $data['actions'][] = $this->actionToArray($action);
+ }
+
+ return $data;
+ }
+
+ /**
+ * @param IAction $action
+ * @return array
+ */
+ protected function actionToArray(IAction $action) {
+ return [
+ 'label' => $action->getParsedLabel(),
+ 'link' => $action->getLink(),
+ 'type' => $action->getRequestType(),
+ 'primary' => $action->isPrimary(),
+ ];
+ }
+
+ /**
+ * @internal
+ * Prepare a notification. This should only be used internally as part of a callback in this
+ * class. Use IManager::prepare to prepare the notification.
+ * @param INotification $notification the notification to be prepared
+ * @param string $language the language to be used
+ * @return INotification|null the prepared notification or null if it couldn't be prepared
+ */
+ public function prepareNotification(INotification $notification, $language) {
+ try {
+ return $this->manager->prepare($notification, $language);
+ } catch (\InvalidArgumentException $e) {
+ // The app was disabled, skip the notification
+ return null;
+ }
+ }
+}
diff --git a/lib/Handler.php b/lib/Handler.php
index 902b3df9..fb9ca2be 100644
--- a/lib/Handler.php
+++ b/lib/Handler.php
@@ -29,6 +29,12 @@
use OCP\Notification\INotification;
class Handler {
+ /**
+ * Used in fetchDescendentList and fetchAscendentList method to limit the number of results
+ * Intended to be used as default value, but a larger value can be set (no enforcement)
+ */
+ const FETCH_DEFAULT_LIMIT = 20;
+
/** @var IDBConnection */
protected $connection;
@@ -159,6 +165,116 @@ public function get(INotification $notification, $limit = 25) {
return $notifications;
}
+ /**
+ * Fetch a list of notifications starting from notification id $id up to $limit number of
+ * notifications. If id = null, we'll start from the newest id available. If there is a
+ * notification matching the id, it will be ignored and won't be returned
+ * @param string $user the target user for the notifications
+ * @param int|null $id the starting notification id (it won't be returned)
+ * @param int $limit the maximum number of notifications that will be fetched
+ * @param callable|null $callable the condition that the notification should match to be part
+ * of the result. The callable will be called with a INotification object as parameter such as
+ * "$callable(INotification $notification)" and must return an INotification object if such
+ * notification should be part of the result or null otherwise
+ * @return array [notification_id => INotification]
+ */
+ public function fetchDescendentList($user, $id = null, $limit = self::FETCH_DEFAULT_LIMIT, $callable = null) {
+ $sql = $this->connection->getQueryBuilder();
+ $sql->select('*')
+ ->from('notifications')
+ ->orderBy('notification_id', 'DESC');
+
+ $sql->where($sql->expr()->eq('user', $sql->createNamedParameter($user)));
+ if ($id !== null) {
+ $sql->andWhere($sql->expr()->lt('notification_id', $sql->createNamedParameter($id, IQueryBuilder::PARAM_INT)));
+ }
+
+ $statement = $sql->execute();
+
+ $notifications = [];
+ $numberOfNotifications = 0;
+ while (($row = $statement->fetch()) && $numberOfNotifications < $limit) {
+ $notification = $this->notificationFromRow($row);
+ $processedNotification = $this->processByCallback($notification, $callable);
+ if ($processedNotification !== null) {
+ $notifications[(int) $row['notification_id']] = $processedNotification;
+ $numberOfNotifications++;
+ }
+ }
+ $statement->closeCursor();
+
+ return $notifications;
+ }
+
+ /**
+ * Fetch a list of notifications starting from notification id $id up to $limit number of
+ * notifications. If id = null, we'll start from the oldest id available. If there is a
+ * notification matching the id, it will be ignored and won't be returned
+ * @param string $user the target user for the notifications
+ * @param int|null $id the starting notification id (it won't be returned)
+ * @param int $limit the maximum number of notifications that will be fetched
+ * @param callable|null $callable the condition that the notification should match to be part
+ * of the result. The callable will be called with a INotification object as parameter such as
+ * "$callable(INotification $notification)" and must return an INotification object if such
+ * notification should be part of the result or null otherwise
+ * @return array [notification_id => INotification]
+ */
+ public function fetchAscendentList($user, $id = null, $limit = self::FETCH_DEFAULT_LIMIT, $callable = null) {
+ $sql = $this->connection->getQueryBuilder();
+ $sql->select('*')
+ ->from('notifications')
+ ->orderBy('notification_id', 'ASC');
+
+ $sql->where($sql->expr()->eq('user', $sql->createNamedParameter($user)));
+ if ($id !== null) {
+ $sql->andWhere($sql->expr()->gt('notification_id', $sql->createNamedParameter($id, IQueryBuilder::PARAM_INT)));
+ }
+
+ $statement = $sql->execute();
+
+ $notifications = [];
+ $numberOfNotifications = 0;
+ while (($row = $statement->fetch()) && $numberOfNotifications < $limit) {
+ $notification = $this->notificationFromRow($row);
+ $processedNotification = $this->processByCallback($notification, $callable);
+ if ($processedNotification !== null) {
+ $notifications[(int) $row['notification_id']] = $processedNotification;
+ $numberOfNotifications++;
+ }
+ }
+ $statement->closeCursor();
+
+ return $notifications;
+ }
+
+ /**
+ * Get the maximum notification id available for the user
+ * @param string $user the user to be filtered with
+ * @return int|null the maximum notification id for the user or null if the user doesn't have
+ * any notification
+ */
+ public function getMaxNotificationId($user) {
+ $sql = $this->connection->getQueryBuilder();
+ $sql->select($sql->createFunction('max(`notification_id`) as `max_id`'))
+ ->from('notifications')
+ ->where($sql->expr()->eq('user', $sql->createNamedParameter($user)));
+
+ $statement = $sql->execute();
+ $row = $statement->fetch();
+ $maxId = $row['max_id'];
+ $statement->closeCursor();
+
+ return $maxId;
+ }
+
+ private function processByCallback(INotification $notification, $callable = null) {
+ if (is_callable($callable)) {
+ return $callable($notification);
+ } else {
+ return $notification;
+ }
+ }
+
/**
* Add where statements to a query builder matching the given notification
*
diff --git a/tests/Unit/Controller/EndpointV2ControllerTest.php b/tests/Unit/Controller/EndpointV2ControllerTest.php
new file mode 100644
index 00000000..64ab923a
--- /dev/null
+++ b/tests/Unit/Controller/EndpointV2ControllerTest.php
@@ -0,0 +1,540 @@
+
+ *
+ * @copyright Copyright (c) 2018, ownCloud GmbH
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see
+ *
+ */
+
+namespace OCA\Notifications\Tests\Unit\Controller;
+
+use OCP\AppFramework\Http;
+use OCP\IUser;
+use OCP\IConfig;
+use OCP\IRequest;
+use OCP\IUserSession;
+use OCP\IURLGenerator;
+use OCP\Notification\IManager;
+use OCP\Notification\INotification;
+use OCP\Notification\IAction;
+use OCA\Notifications\Handler;
+use OCA\Notifications\Controller\EndpointV2Controller;
+
+class EndpointV2ControllerTest extends \Test\TestCase {
+ /** @var Handler */
+ private $handler;
+
+ /** @var IManager */
+ private $manager;
+
+ /** @var IUserSession */
+ private $userSession;
+
+ /** @var IConfig */
+ private $config;
+
+ /** @var IURLGenerator */
+ private $urlGenerator;
+
+ /** @var EndpointV2Controller */
+ private $controller;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->request = $this->getMockBuilder(IRequest::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->handler = $this->getMockBuilder(Handler::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->manager = $this->getMockBuilder(IManager::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->userSession = $this->getMockBuilder(IUserSession::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->config = $this->getMockBuilder(IConfig::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->urlGenerator = $this->getMockBuilder(IURLGenerator::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->controller = new EndpointV2Controller($this->handler, $this->manager, $this->userSession, $this->config, $this->urlGenerator, $this->request);
+ }
+
+ private function getNotificationList() {
+ $result = [];
+ $action = $this->getMockBuilder(IAction::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $action->method('getParsedLabel')
+ ->willReturn('qwerty');
+ $action->method('getLink')
+ ->willReturn('link');
+ $action->method('getRequestType')
+ ->willReturn('HEAD');
+ $action->method('isPrimary')
+ ->willReturn(false);
+ for ($i = 5; $i <= 40; $i++) {
+ $notification = $this->getMockBuilder(INotification::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $notification->method('getObjectType')
+ ->willReturn('test_notification');
+ $notification->method('getObjectId')
+ ->willReturn(strval($i));
+ $notification->method('getDateTime')
+ ->willReturn(new \DateTime());
+
+ if ($i > 30) {
+ $notification->method('getParsedActions')
+ ->willReturn([$action]);
+ } else {
+ $notification->method('getParsedActions')
+ ->willReturn([]);
+ }
+ $result[$i] = $notification;
+ }
+ return $result;
+ }
+
+ private function isKeySortedBottomToTop(array $arr) {
+ $previousId = null;
+ foreach ($arr as $key => $value) {
+ if ($previousId !== null) {
+ if ($previousId > $value['notification_id']) {
+ return false;
+ }
+ }
+ $previousId = $value['notification_id'];
+ }
+ return true;
+ }
+
+ private function isKeySortedTopToBottom(array $arr) {
+ $previousId = null;
+ foreach ($arr as $key => $value) {
+ if ($previousId !== null) {
+ if ($previousId < $value['notification_id']) {
+ return false;
+ }
+ }
+ $previousId = $value['notification_id'];
+ }
+ return true;
+ }
+
+ public function testListNotificationsWrongUser() {
+ $this->userSession->method('getUser')
+ ->willReturn(null);
+
+ $this->assertEquals(Http::STATUS_FORBIDDEN, $this->controller->listNotifications()->getStatus());
+ }
+
+ /**
+ * the id is forwarded directly to the handler, so no need to test with different ids
+ */
+ public function testListNotificationsDescendent() {
+ $maxResults = EndpointV2Controller::ENFORCED_LIST_LIMIT;
+ $notificationList = $this->getNotificationList();
+ krsort($notificationList);
+ $notificationList = array_slice($notificationList, 0, $maxResults + 1, true);
+
+ $user = $this->getMockBuilder(IUser::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $user->method('getUID')
+ ->willReturn('test_user1');
+ $this->userSession->method('getUser')
+ ->willReturn($user);
+
+ $this->handler->method('getMaxNotificationId')
+ ->willReturn(123); // purposely use a different max id than the one returned in the list
+ $this->handler->method('fetchDescendentList')
+ ->with('test_user1', null, $maxResults + 1, $this->anything())
+ ->willReturn($notificationList);
+
+ $this->manager->method('prepare')
+ ->will($this->returnArgument(0));
+
+ $this->urlGenerator->method('linkToRoute')
+ ->willReturn('http://server/owncloud/route?id=20&fetch=desc&limit=20');
+ // we won't check the url returned by the urlGenerator, any path will do
+
+ $ocsResult = $this->controller->listNotifications();
+ $this->assertEquals(Http::STATUS_OK, $ocsResult->getStatus());
+
+ $rawData = json_decode($ocsResult->render(), true);
+ $rawData = $rawData['ocs']['data'];
+ $this->assertEquals($maxResults, count($rawData['notifications']));
+ $this->assertTrue($this->isKeySortedTopToBottom($rawData['notifications']));
+ $this->assertArrayHasKey('next', $rawData);
+ $this->assertEquals('http://server/owncloud/route?id=20&fetch=desc&limit=20', $rawData['next']);
+
+ $resultHeaders = $ocsResult->getHeaders();
+ $this->assertArrayHasKey('OC-Last-Notification', $resultHeaders);
+ $this->assertEquals(123, $resultHeaders['OC-Last-Notification']);
+ }
+
+ public function testListNotificationsDescendentNoNotifications() {
+ $maxResults = EndpointV2Controller::ENFORCED_LIST_LIMIT;
+ $notificationList = $this->getNotificationList();
+ krsort($notificationList);
+ $notificationList = array_slice($notificationList, 0, $maxResults + 1, true);
+
+ $user = $this->getMockBuilder(IUser::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $user->method('getUID')
+ ->willReturn('test_user1');
+ $this->userSession->method('getUser')
+ ->willReturn($user);
+
+ $this->handler->method('getMaxNotificationId')
+ ->willReturn(null); // purposely use a different max id than the one returned in the list
+ $this->handler->method('fetchDescendentList')
+ ->with('test_user1', null, $maxResults + 1, $this->anything())
+ ->willReturn([]);
+
+ $this->manager->method('prepare')
+ ->will($this->returnArgument(0));
+
+ $this->urlGenerator->method('linkToRoute')
+ ->willReturn('http://server/owncloud/route?id=20&fetch=desc&limit=20');
+ // we won't check the url returned by the urlGenerator, any path will do
+
+ $ocsResult = $this->controller->listNotifications();
+ $this->assertEquals(Http::STATUS_OK, $ocsResult->getStatus());
+
+ $rawData = json_decode($ocsResult->render(), true);
+ $rawData = $rawData['ocs']['data'];
+ $this->assertEquals(0, count($rawData['notifications']));
+ $this->assertTrue($this->isKeySortedTopToBottom($rawData['notifications']));
+ $this->assertArrayNotHasKey('next', $rawData);
+
+ $resultHeaders = $ocsResult->getHeaders();
+ $this->assertArrayHasKey('OC-Last-Notification', $resultHeaders);
+ $this->assertEquals(-1, $resultHeaders['OC-Last-Notification']); // header should return -1 instead of null
+ }
+
+ /**
+ * the id is forwarded directly to the handler, so need to test with different ids
+ */
+ public function testListNotificationsAscendent() {
+ $maxResults = EndpointV2Controller::ENFORCED_LIST_LIMIT;
+ $notificationList = $this->getNotificationList();
+ $notificationList = array_slice($notificationList, 0, $maxResults + 1, true);
+
+ $user = $this->getMockBuilder(IUser::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $user->method('getUID')
+ ->willReturn('test_user1');
+ $this->userSession->method('getUser')
+ ->willReturn($user);
+
+ $this->handler->method('getMaxNotificationId')
+ ->willReturn(123); // purposely use a different max id than the one returned in the list
+ $this->handler->method('fetchAscendentList')
+ ->with('test_user1', null, $maxResults + 1, $this->anything())
+ ->willReturn($notificationList);
+
+ $this->manager->method('prepare')
+ ->will($this->returnArgument(0));
+
+ $this->urlGenerator->method('linkToRoute')
+ ->willReturn('http://server/owncloud/route?id=20&fetch=asc&limit=20');
+ // we won't check the url returned by the urlGenerator, any path will do
+
+ $ocsResult = $this->controller->listNotifications(null, 'asc');
+ $this->assertEquals(Http::STATUS_OK, $ocsResult->getStatus());
+
+ $rawData = json_decode($ocsResult->render(), true);
+ $rawData = $rawData['ocs']['data'];
+ $this->assertEquals($maxResults, count($rawData['notifications']));
+ $this->assertTrue($this->isKeySortedBottomToTop($rawData['notifications']));
+ $this->assertArrayHasKey('next', $rawData);
+ $this->assertEquals('http://server/owncloud/route?id=20&fetch=asc&limit=20', $rawData['next']);
+
+ $resultHeaders = $ocsResult->getHeaders();
+ $this->assertArrayHasKey('OC-Last-Notification', $resultHeaders);
+ $this->assertEquals(123, $resultHeaders['OC-Last-Notification']);
+ }
+
+ public function testListNotificationsAscendentNoNotifications() {
+ $maxResults = EndpointV2Controller::ENFORCED_LIST_LIMIT;
+ $notificationList = $this->getNotificationList();
+ $notificationList = array_slice($notificationList, 0, $maxResults + 1, true);
+
+ $user = $this->getMockBuilder(IUser::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $user->method('getUID')
+ ->willReturn('test_user1');
+ $this->userSession->method('getUser')
+ ->willReturn($user);
+
+ $this->handler->method('getMaxNotificationId')
+ ->willReturn(null);
+ $this->handler->method('fetchAscendentList')
+ ->with('test_user1', null, $maxResults + 1, $this->anything())
+ ->willReturn([]);
+
+ $this->manager->method('prepare')
+ ->will($this->returnArgument(0));
+
+ $this->urlGenerator->method('linkToRoute')
+ ->willReturn('http://server/owncloud/route?id=20&fetch=asc&limit=20');
+ // we won't check the url returned by the urlGenerator, any path will do
+
+ $ocsResult = $this->controller->listNotifications(null, 'asc');
+ $this->assertEquals(Http::STATUS_OK, $ocsResult->getStatus());
+
+ $rawData = json_decode($ocsResult->render(), true);
+ $rawData = $rawData['ocs']['data'];
+ $this->assertEquals(0, count($rawData['notifications']));
+ $this->assertTrue($this->isKeySortedBottomToTop($rawData['notifications']));
+ $this->assertArrayNotHasKey('next', $rawData);
+
+ $resultHeaders = $ocsResult->getHeaders();
+ $this->assertArrayHasKey('OC-Last-Notification', $resultHeaders);
+ $this->assertEquals(-1, $resultHeaders['OC-Last-Notification']);
+ }
+
+ public function testListNotificationsDescendentNoMoreResults() {
+ $maxResults = EndpointV2Controller::ENFORCED_LIST_LIMIT;
+ $notificationList = $this->getNotificationList();
+ krsort($notificationList);
+ $notificationList = array_slice($notificationList, 0, $maxResults + 1, true);
+
+ $user = $this->getMockBuilder(IUser::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $user->method('getUID')
+ ->willReturn('test_user1');
+ $this->userSession->method('getUser')
+ ->willReturn($user);
+
+ $this->handler->method('getMaxNotificationId')
+ ->willReturn(123); // purposely use a different max id than the one returned in the list
+ $this->handler->method('fetchDescendentList')
+ ->with('test_user1', null, $maxResults + 1, $this->anything())
+ ->willReturn(array_slice($notificationList, 0, 3, true));
+
+ $this->manager->method('prepare')
+ ->will($this->returnArgument(0));
+
+ $ocsResult = $this->controller->listNotifications();
+ $this->assertEquals(Http::STATUS_OK, $ocsResult->getStatus());
+
+ $rawData = json_decode($ocsResult->render(), true);
+ $rawData = $rawData['ocs']['data'];
+ $this->assertLessThan($maxResults, count($rawData['notifications']));
+ $this->assertTrue($this->isKeySortedTopToBottom($rawData['notifications']));
+ $this->assertArrayNotHasKey('next', $rawData);
+
+ $resultHeaders = $ocsResult->getHeaders();
+ $this->assertArrayHasKey('OC-Last-Notification', $resultHeaders);
+ $this->assertEquals(123, $resultHeaders['OC-Last-Notification']);
+ }
+
+ public function testGetNotificationWrongUser() {
+ $this->userSession->method('getUser')
+ ->willReturn(null);
+
+ $this->assertEquals(Http::STATUS_FORBIDDEN, $this->controller->getNotification(5)->getStatus());
+ }
+
+ public function testGetNotificationNotNotificationType() {
+ $user = $this->getMockBuilder(IUser::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $user->method('getUID')
+ ->willReturn('test_user1');
+ $this->userSession->method('getUser')
+ ->willReturn($user);
+
+ $this->handler->method('getById')
+ ->willReturn(false);
+
+ $this->assertEquals(Http::STATUS_NOT_FOUND, $this->controller->getNotification(5)->getStatus());
+ }
+
+ public function testGetNotificationCannotPrepare() {
+ $user = $this->getMockBuilder(IUser::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $user->method('getUID')
+ ->willReturn('test_user1');
+ $this->userSession->method('getUser')
+ ->willReturn($user);
+
+ $notification = $this->getMockBuilder(INotification::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $notification->method('getObjectType')
+ ->willReturn('test_notification');
+ $notification->method('getObjectId')
+ ->willReturn('21');
+ $notification->method('getDateTime')
+ ->willReturn(new \DateTime());
+ $notification->method('getParsedActions')
+ ->willReturn([]);
+
+ $this->handler->method('getById')
+ ->willReturn($notification);
+
+ $this->manager->method('prepare')
+ ->will($this->throwException(new \InvalidArgumentException()));
+
+ $this->assertEquals(Http::STATUS_NOT_FOUND, $this->controller->getNotification(5)->getStatus());
+ }
+
+ public function testGetNotification() {
+ $user = $this->getMockBuilder(IUser::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $user->method('getUID')
+ ->willReturn('test_user1');
+ $this->userSession->method('getUser')
+ ->willReturn($user);
+
+ $datetime = new \DateTime();
+ $notification = $this->getMockBuilder(INotification::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $notification->method('getObjectType')
+ ->willReturn('test_notification');
+ $notification->method('getObjectId')
+ ->willReturn('21');
+ $notification->method('getDateTime')
+ ->willReturn($datetime);
+ $notification->method('getParsedSubject')
+ ->willReturn('the parsed subject');
+ $notification->method('getParsedActions')
+ ->willReturn([]);
+
+ $this->handler->method('getById')
+ ->willReturn($notification);
+
+ $this->manager->method('prepare')
+ ->willReturn($notification);
+
+ $ocsResult = $this->controller->getNotification(5);
+ $this->assertEquals(Http::STATUS_OK, $ocsResult->getStatus());
+
+ $rawData = json_decode($ocsResult->render(), true);
+ $rawData = $rawData['ocs']['data'];
+ $this->assertEquals('5', $rawData['notification_id']);
+ $this->assertEquals($datetime->format('c'), $rawData['datetime']);
+ $this->assertEquals('the parsed subject', $rawData['subject']);
+ $this->assertEquals([], $rawData['actions']);
+ }
+
+ public function testDeleteNotificationWrongUser() {
+ $this->userSession->method('getUser')
+ ->willReturn(null);
+
+ $this->assertEquals(Http::STATUS_FORBIDDEN, $this->controller->deleteNotification(5)->getStatus());
+ }
+
+ public function testDeleteNotification() {
+ $user = $this->getMockBuilder(IUser::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $user->method('getUID')
+ ->willReturn('test_user1');
+ $this->userSession->method('getUser')
+ ->willReturn($user);
+
+ $this->assertEquals(Http::STATUS_OK, $this->controller->deleteNotification(5)->getStatus());
+ }
+
+ public function testGetLastNotificationIdWrongUser() {
+ $this->userSession->method('getUser')
+ ->willReturn(null);
+
+ $this->assertEquals(Http::STATUS_FORBIDDEN, $this->controller->getLastNotificationId(5)->getStatus());
+ }
+
+ public function testGetLastNotification() {
+ $user = $this->getMockBuilder(IUser::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $user->method('getUID')
+ ->willReturn('test_user1');
+ $this->userSession->method('getUser')
+ ->willReturn($user);
+
+ $this->handler->method('getMaxNotificationId')
+ ->willReturn(321);
+
+ $ocsResult = $this->controller->getLastNotificationId();
+ $this->assertEquals(Http::STATUS_OK, $ocsResult->getStatus());
+
+ $rawData = json_decode($ocsResult->render(), true);
+ $rawData = $rawData['ocs']['data'];
+ $this->assertEquals(['id' => 321], $rawData);
+
+ $resultHeaders = $ocsResult->getHeaders();
+ $this->assertArrayHasKey('OC-Last-Notification', $resultHeaders);
+ $this->assertEquals(321, $resultHeaders['OC-Last-Notification']);
+ }
+
+ public function testGetLastNotificationNoNotifications() {
+ $user = $this->getMockBuilder(IUser::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $user->method('getUID')
+ ->willReturn('test_user1');
+ $this->userSession->method('getUser')
+ ->willReturn($user);
+
+ $this->handler->method('getMaxNotificationId')
+ ->willReturn(null);
+
+ $ocsResult = $this->controller->getLastNotificationId();
+ $this->assertEquals(Http::STATUS_OK, $ocsResult->getStatus());
+
+ $rawData = json_decode($ocsResult->render(), true);
+ $rawData = $rawData['ocs']['data'];
+ $this->assertEquals(['id' => -1], $rawData);
+
+ $resultHeaders = $ocsResult->getHeaders();
+ $this->assertArrayHasKey('OC-Last-Notification', $resultHeaders);
+ $this->assertEquals(-1, $resultHeaders['OC-Last-Notification']);
+ }
+
+ public function testPrepareNotification() {
+ $notification = $this->getMockBuilder(INotification::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->manager->method('prepare')
+ ->will($this->returnArgument(0));
+ $this->assertInstanceOf(INotification::class, $this->controller->prepareNotification($notification, 'en_US'));
+ }
+
+ public function testPrepareNotificationInvalid() {
+ $notification = $this->getMockBuilder(INotification::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->manager->method('prepare')
+ ->will($this->throwException(new \InvalidArgumentException()));
+ $this->assertNull($this->controller->prepareNotification($notification, 'en_US'));
+ }
+}
diff --git a/tests/Unit/HandlerTest.php b/tests/Unit/HandlerTest.php
index cd686b2b..c5f3fde9 100644
--- a/tests/Unit/HandlerTest.php
+++ b/tests/Unit/HandlerTest.php
@@ -22,8 +22,8 @@
namespace OCA\Notifications\Tests\Unit;
-
use OCA\Notifications\Handler;
+use OCP\Notification\INotification;
/**
* Class HandlerTest
@@ -161,19 +161,379 @@ public function testDeleteById() {
// Get with correct user
$getNotification = $this->handler->getById($notificationId, 'test_user1');
- $this->assertInstanceOf('OCP\Notification\INotification', $getNotification);
+ $this->assertInstanceOf(INotification::class, $getNotification);
// Delete and count
$this->handler->deleteById($notificationId, 'test_user1');
$this->assertSame(0, $this->handler->count($limitedNotification), 'Wrong notification count for user1 after deleting');
}
+ public function testFetchDescendentList() {
+ $notification1 = $this->getNotification([
+ 'getApp' => 'testing_notifications',
+ 'getUser' => 'test_user1',
+ 'getDateTime' => new \DateTime(),
+ 'getObjectType' => 'notification',
+ 'getObjectId' => '1337',
+ 'getSubject' => 'subject',
+ 'getSubjectParameters' => [],
+ 'getMessage' => 'message',
+ 'getMessageParameters' => [],
+ 'getLink' => 'link',
+ 'getActions' => [
+ [
+ 'getLabel' => 'action_label',
+ 'getLink' => 'action_link',
+ 'getRequestType' => 'GET',
+ 'isPrimary' => true,
+ ]
+ ],
+ ]);
+ $notification2 = $this->getNotification([
+ 'getApp' => 'testing_notifications',
+ 'getUser' => 'test_user2',
+ 'getDateTime' => new \DateTime(),
+ 'getObjectType' => 'notifi-cat-ion',
+ 'getObjectId' => '1338',
+ 'getSubject' => 'subject',
+ 'getSubjectParameters' => [],
+ 'getMessage' => 'message',
+ 'getMessageParameters' => [],
+ 'getLink' => 'link',
+ 'getActions' => [
+ [
+ 'getLabel' => 'action_label',
+ 'getLink' => 'action_link',
+ 'getRequestType' => 'GET',
+ 'isPrimary' => true,
+ ]
+ ],
+ ]);
+ $notification3 = $this->getNotification([
+ 'getApp' => 'testing_notifications',
+ 'getUser' => 'test_user1',
+ 'getDateTime' => new \DateTime(),
+ 'getObjectType' => 'blondification',
+ 'getObjectId' => '1339',
+ 'getSubject' => 'subject',
+ 'getSubjectParameters' => [],
+ 'getMessage' => 'message',
+ 'getMessageParameters' => [],
+ 'getLink' => 'link',
+ 'getActions' => [
+ [
+ 'getLabel' => 'action_label',
+ 'getLink' => 'action_link',
+ 'getRequestType' => 'GET',
+ 'isPrimary' => true,
+ ]
+ ],
+ ]);
+ $notification4 = $this->getNotification([
+ 'getApp' => 'testing_notifications',
+ 'getUser' => 'test_user1',
+ 'getDateTime' => new \DateTime(),
+ 'getObjectType' => 'nonefination',
+ 'getObjectId' => '1340',
+ 'getSubject' => 'subject',
+ 'getSubjectParameters' => [],
+ 'getMessage' => 'message',
+ 'getMessageParameters' => [],
+ 'getLink' => 'link',
+ 'getActions' => [
+ [
+ 'getLabel' => 'action_label',
+ 'getLink' => 'action_link',
+ 'getRequestType' => 'GET',
+ 'isPrimary' => true,
+ ]
+ ],
+ ]);
+ $this->handler->add($notification1);
+ $this->handler->add($notification2);
+ $this->handler->add($notification3);
+ $this->handler->add($notification4);
+
+ // fetch all the notifications (up to 20)
+ $list = $this->handler->fetchDescendentList('test_user1');
+ $listKeys = array_keys($list);
+ $this->assertEquals(3, count($list));
+ $this->assertEquals('nonefination', $list[$listKeys[0]]->getObjectType());
+ $this->assertEquals('blondification', $list[$listKeys[1]]->getObjectType());
+ $this->assertEquals('notification', $list[$listKeys[2]]->getObjectType());
+ $this->assertTrue($listKeys[0] > $listKeys[1]);
+ $this->assertTrue($listKeys[1] > $listKeys[2]);
+
+ $list2 = $this->handler->fetchDescendentList('test_user1', $listKeys[1]);
+ $listKeys2 = array_keys($list2);
+ $this->assertEquals(1, count($list2)); // only 1 since the id specified won't be included
+ $this->assertEquals('notification', $list[$listKeys2[0]]->getObjectType());
+ $this->assertEquals($listKeys[2], $listKeys2[0]); // check the id of the notification
+
+ $list3 = $this->handler->fetchDescendentList('test_user1', null, 1);
+ $listKeys3 = array_keys($list3);
+ $this->assertEquals(1, count($list3)); // only 1 since the id specified won't be included
+ $this->assertEquals('nonefination', $list[$listKeys3[0]]->getObjectType());
+ $this->assertEquals($listKeys[0], $listKeys3[0]); // check the id of the notification
+
+ $list4 = $this->handler->fetchDescendentList('test_user1', $listKeys[0], 1);
+ $listKeys4 = array_keys($list4);
+ $this->assertEquals(1, count($list4)); // only 1 since the id specified won't be included
+ $this->assertEquals('blondification', $list[$listKeys4[0]]->getObjectType());
+ $this->assertEquals($listKeys[1], $listKeys4[0]); // check the id of the notification
+
+ $callableFunc = function(INotification $notification) {
+ if (strpos($notification->getObjectType(), 'no') === 0) {
+ return $notification;
+ } else {
+ return null;
+ }
+ };
+
+ $list5 = $this->handler->fetchDescendentList('test_user1', null, 20, $callableFunc);
+ $listKeys5 = array_keys($list5);
+ $this->assertEquals(2, count($list5)); // only 1 since the id specified won't be included
+ $this->assertEquals('nonefination', $list[$listKeys5[0]]->getObjectType());
+ $this->assertEquals('notification', $list[$listKeys5[1]]->getObjectType());
+ $this->assertTrue($listKeys5[0] > $listKeys5[1]);
+ $this->assertEquals($listKeys[0], $listKeys5[0]); // check the id of the notification
+ $this->assertEquals($listKeys[2], $listKeys5[1]);
+
+ $this->handler->delete($notification1);
+ $this->handler->delete($notification2);
+ $this->handler->delete($notification3);
+ $this->handler->delete($notification4);
+ }
+
+ public function testFetchAscendentList() {
+ $notification1 = $this->getNotification([
+ 'getApp' => 'testing_notifications',
+ 'getUser' => 'test_user1',
+ 'getDateTime' => new \DateTime(),
+ 'getObjectType' => 'notification',
+ 'getObjectId' => '1337',
+ 'getSubject' => 'subject',
+ 'getSubjectParameters' => [],
+ 'getMessage' => 'message',
+ 'getMessageParameters' => [],
+ 'getLink' => 'link',
+ 'getActions' => [
+ [
+ 'getLabel' => 'action_label',
+ 'getLink' => 'action_link',
+ 'getRequestType' => 'GET',
+ 'isPrimary' => true,
+ ]
+ ],
+ ]);
+ $notification2 = $this->getNotification([
+ 'getApp' => 'testing_notifications',
+ 'getUser' => 'test_user2',
+ 'getDateTime' => new \DateTime(),
+ 'getObjectType' => 'notifi-cat-ion',
+ 'getObjectId' => '1338',
+ 'getSubject' => 'subject',
+ 'getSubjectParameters' => [],
+ 'getMessage' => 'message',
+ 'getMessageParameters' => [],
+ 'getLink' => 'link',
+ 'getActions' => [
+ [
+ 'getLabel' => 'action_label',
+ 'getLink' => 'action_link',
+ 'getRequestType' => 'GET',
+ 'isPrimary' => true,
+ ]
+ ],
+ ]);
+ $notification3 = $this->getNotification([
+ 'getApp' => 'testing_notifications',
+ 'getUser' => 'test_user1',
+ 'getDateTime' => new \DateTime(),
+ 'getObjectType' => 'blondification',
+ 'getObjectId' => '1339',
+ 'getSubject' => 'subject',
+ 'getSubjectParameters' => [],
+ 'getMessage' => 'message',
+ 'getMessageParameters' => [],
+ 'getLink' => 'link',
+ 'getActions' => [
+ [
+ 'getLabel' => 'action_label',
+ 'getLink' => 'action_link',
+ 'getRequestType' => 'GET',
+ 'isPrimary' => true,
+ ]
+ ],
+ ]);
+ $notification4 = $this->getNotification([
+ 'getApp' => 'testing_notifications',
+ 'getUser' => 'test_user1',
+ 'getDateTime' => new \DateTime(),
+ 'getObjectType' => 'nonefination',
+ 'getObjectId' => '1340',
+ 'getSubject' => 'subject',
+ 'getSubjectParameters' => [],
+ 'getMessage' => 'message',
+ 'getMessageParameters' => [],
+ 'getLink' => 'link',
+ 'getActions' => [
+ [
+ 'getLabel' => 'action_label',
+ 'getLink' => 'action_link',
+ 'getRequestType' => 'GET',
+ 'isPrimary' => true,
+ ]
+ ],
+ ]);
+ $this->handler->add($notification1);
+ $this->handler->add($notification2);
+ $this->handler->add($notification3);
+ $this->handler->add($notification4);
+
+ // fetch all the notifications (up to 20)
+ $list = $this->handler->fetchAscendentList('test_user1');
+ $listKeys = array_keys($list);
+ $this->assertEquals(3, count($list));
+ $this->assertEquals('notification', $list[$listKeys[0]]->getObjectType());
+ $this->assertEquals('blondification', $list[$listKeys[1]]->getObjectType());
+ $this->assertEquals('nonefination', $list[$listKeys[2]]->getObjectType());
+ $this->assertTrue($listKeys[0] < $listKeys[1]);
+ $this->assertTrue($listKeys[1] < $listKeys[2]);
+
+ $list2 = $this->handler->fetchAscendentList('test_user1', $listKeys[1]);
+ $listKeys2 = array_keys($list2);
+ $this->assertEquals(1, count($list2)); // only 1 since the id specified won't be included
+ $this->assertEquals('nonefination', $list[$listKeys2[0]]->getObjectType());
+ $this->assertEquals($listKeys[2], $listKeys2[0]); // check the id of the notification
+
+ $list3 = $this->handler->fetchAscendentList('test_user1', null, 1);
+ $listKeys3 = array_keys($list3);
+ $this->assertEquals(1, count($list3)); // only 1 since the id specified won't be included
+ $this->assertEquals('notification', $list[$listKeys3[0]]->getObjectType());
+ $this->assertEquals($listKeys[0], $listKeys3[0]); // check the id of the notification
+
+ $list4 = $this->handler->fetchAscendentList('test_user1', $listKeys[0], 1);
+ $listKeys4 = array_keys($list4);
+ $this->assertEquals(1, count($list4)); // only 1 since the id specified won't be included
+ $this->assertEquals('blondification', $list[$listKeys4[0]]->getObjectType());
+ $this->assertEquals($listKeys[1], $listKeys4[0]); // check the id of the notification
+
+ $callableFunc = function(INotification $notification) {
+ if (strpos($notification->getObjectType(), 'no') === 0) {
+ return $notification;
+ } else {
+ return null;
+ }
+ };
+
+ $list5 = $this->handler->fetchAscendentList('test_user1', null, 20, $callableFunc);
+ $listKeys5 = array_keys($list5);
+ $this->assertEquals(2, count($list5)); // only 1 since the id specified won't be included
+ $this->assertEquals('notification', $list[$listKeys5[0]]->getObjectType());
+ $this->assertEquals('nonefination', $list[$listKeys5[1]]->getObjectType());
+ $this->assertTrue($listKeys5[0] < $listKeys5[1]);
+ $this->assertEquals($listKeys[0], $listKeys5[0]); // check the id of the notification
+ $this->assertEquals($listKeys[2], $listKeys5[1]);
+
+ $this->handler->delete($notification1);
+ $this->handler->delete($notification2);
+ $this->handler->delete($notification3);
+ $this->handler->delete($notification4);
+ }
+
+ public function testGetMaxNotificationIdNoNotifications() {
+ $user = uniqid('test_user_'); // any non-existing user is good
+ $this->assertNull($this->handler->getMaxNotificationId($user));
+ }
+
+ public function testGetMaxNotificationId() {
+ $notification1 = $this->getNotification([
+ 'getApp' => 'testing_notifications',
+ 'getUser' => 'test_user1',
+ 'getDateTime' => new \DateTime(),
+ 'getObjectType' => 'notification',
+ 'getObjectId' => '1337',
+ 'getSubject' => 'subject',
+ 'getSubjectParameters' => [],
+ 'getMessage' => 'message',
+ 'getMessageParameters' => [],
+ 'getLink' => 'link',
+ 'getActions' => [
+ [
+ 'getLabel' => 'action_label',
+ 'getLink' => 'action_link',
+ 'getRequestType' => 'GET',
+ 'isPrimary' => true,
+ ]
+ ],
+ ]);
+ $notification3 = $this->getNotification([
+ 'getApp' => 'testing_notifications',
+ 'getUser' => 'test_user1',
+ 'getDateTime' => new \DateTime(),
+ 'getObjectType' => 'blondification',
+ 'getObjectId' => '1339',
+ 'getSubject' => 'subject',
+ 'getSubjectParameters' => [],
+ 'getMessage' => 'message',
+ 'getMessageParameters' => [],
+ 'getLink' => 'link',
+ 'getActions' => [
+ [
+ 'getLabel' => 'action_label',
+ 'getLink' => 'action_link',
+ 'getRequestType' => 'GET',
+ 'isPrimary' => true,
+ ]
+ ],
+ ]);
+ $notification4 = $this->getNotification([
+ 'getApp' => 'testing_notifications',
+ 'getUser' => 'test_user1',
+ 'getDateTime' => new \DateTime(),
+ 'getObjectType' => 'nonefination',
+ 'getObjectId' => '1340',
+ 'getSubject' => 'subject',
+ 'getSubjectParameters' => [],
+ 'getMessage' => 'message',
+ 'getMessageParameters' => [],
+ 'getLink' => 'link',
+ 'getActions' => [
+ [
+ 'getLabel' => 'action_label',
+ 'getLink' => 'action_link',
+ 'getRequestType' => 'GET',
+ 'isPrimary' => true,
+ ]
+ ],
+ ]);
+ $this->handler->add($notification1);
+ $this->handler->add($notification3);
+ $this->handler->add($notification4);
+
+ $maxId = $this->handler->getMaxNotificationId('test_user1');
+
+ $limitedNotification = $this->getNotification([
+ 'getApp' => 'testing_notifications',
+ 'getUser' => 'test_user1',
+ ]);
+ $notificationList = $this->handler->get($limitedNotification);
+ $expectedMaxId = -1;
+ foreach ($notificationList as $key => $value) {
+ if ($key > $expectedMaxId) {
+ $expectedMaxId = $key;
+ }
+ }
+ $this->assertEquals($expectedMaxId, $maxId);
+ }
+
/**
* @param array $values
* @return \OCP\Notification\INotification|\PHPUnit_Framework_MockObject_MockObject
*/
protected function getNotification(array $values = []) {
- $notification = $this->getMockBuilder('OCP\Notification\INotification')
+ $notification = $this->getMockBuilder(INotification::class)
->disableOriginalConstructor()
->getMock();