Browse Source

Merge pull request #18699 from owncloud/notification-manager

Notification manager
remotes/origin/db-empty-migrate
Lukas Reschke 10 years ago
parent
commit
fb717f254f
  1. 1
      apps/files_sharing/ajax/external.php
  2. 4
      apps/files_sharing/api/remote.php
  3. 23
      apps/files_sharing/api/server2server.php
  4. 7
      apps/files_sharing/appinfo/app.php
  5. 1
      apps/files_sharing/appinfo/application.php
  6. 24
      apps/files_sharing/lib/external/manager.php
  7. 1
      apps/files_sharing/lib/hooks.php
  8. 86
      apps/files_sharing/lib/notifier.php
  9. 1
      apps/files_sharing/tests/external/managertest.php
  10. 1
      apps/files_sharing/tests/server2server.php
  11. 167
      lib/private/notification/action.php
  12. 109
      lib/private/notification/iaction.php
  13. 56
      lib/private/notification/iapp.php
  14. 56
      lib/private/notification/imanager.php
  15. 241
      lib/private/notification/inotification.php
  16. 43
      lib/private/notification/inotifier.php
  17. 191
      lib/private/notification/manager.php
  18. 446
      lib/private/notification/notification.php
  19. 14
      lib/private/server.php
  20. 9
      lib/public/iservercontainer.php
  21. 236
      tests/lib/notification/actiontest.php
  22. 345
      tests/lib/notification/managertest.php
  23. 601
      tests/lib/notification/notificationtest.php
  24. 2
      tests/lib/server.php

1
apps/files_sharing/ajax/external.php

@ -52,6 +52,7 @@ $externalManager = new \OCA\Files_Sharing\External\Manager(
\OC\Files\Filesystem::getMountManager(),
\OC\Files\Filesystem::getLoader(),
\OC::$server->getHTTPHelper(),
\OC::$server->getNotificationManager(),
\OC::$server->getUserSession()->getUser()->getUID()
);

4
apps/files_sharing/api/remote.php

@ -38,6 +38,7 @@ class Remote {
Filesystem::getMountManager(),
Filesystem::getLoader(),
\OC::$server->getHTTPHelper(),
\OC::$server->getNotificationManager(),
\OC_User::getUser()
);
@ -56,6 +57,7 @@ class Remote {
Filesystem::getMountManager(),
Filesystem::getLoader(),
\OC::$server->getHTTPHelper(),
\OC::$server->getNotificationManager(),
\OC_User::getUser()
);
@ -78,6 +80,7 @@ class Remote {
Filesystem::getMountManager(),
Filesystem::getLoader(),
\OC::$server->getHTTPHelper(),
\OC::$server->getNotificationManager(),
\OC_User::getUser()
);
@ -87,5 +90,4 @@ class Remote {
return new \OC_OCS_Result(null, 404, "wrong share ID, share doesn't exist.");
}
}

23
apps/files_sharing/api/server2server.php

@ -70,6 +70,7 @@ class Server2Server {
\OC\Files\Filesystem::getMountManager(),
\OC\Files\Filesystem::getLoader(),
\OC::$server->getHTTPHelper(),
\OC::$server->getNotificationManager(),
$shareWith
);
@ -82,6 +83,28 @@ class Server2Server {
Activity::FILES_SHARING_APP, Activity::SUBJECT_REMOTE_SHARE_RECEIVED, array($user, trim($name, '/')), '', array(),
'', '', $shareWith, Activity::TYPE_REMOTE_SHARE, Activity::PRIORITY_LOW);
$urlGenerator = \OC::$server->getURLGenerator();
$notificationManager = \OC::$server->getNotificationManager();
$notification = $notificationManager->createNotification();
$notification->setApp('files_sharing')
->setUser($shareWith)
->setTimestamp(time())
->setObject('remote_share', $remoteId)
->setSubject('remote_share', [$user, trim($name, '/')]);
$acceptAction = $notification->createAction();
$acceptAction->setLabel('accept')
->setLink($urlGenerator->getAbsoluteURL('/ocs/v1.php/apps/files_sharing/api/v1/remote_shares/' . $remoteId), 'POST');
$declineAction = $notification->createAction();
$declineAction->setLabel('decline')
->setLink($urlGenerator->getAbsoluteURL('/ocs/v1.php/apps/files_sharing/api/v1/remote_shares/' . $remoteId), 'DELETE');
$notification->addAction($acceptAction)
->addAction($declineAction);
$notificationManager->notify($notification);
return new \OC_OCS_Result();
} catch (\Exception $e) {
\OCP\Util::writeLog('files_sharing', 'server can not add remote share, ' . $e->getMessage(), \OCP\Util::ERROR);

7
apps/files_sharing/appinfo/app.php

@ -103,3 +103,10 @@ if ($config->getAppValue('core', 'shareapi_enabled', 'yes') === 'yes') {
}
}
}
$manager = \OC::$server->getNotificationManager();
$manager->registerNotifier(function() {
return new \OCA\Files_Sharing\Notifier(
\OC::$server->getL10NFactory()
);
});

1
apps/files_sharing/appinfo/application.php

@ -93,6 +93,7 @@ class Application extends App {
\OC\Files\Filesystem::getMountManager(),
\OC\Files\Filesystem::getLoader(),
$server->getHTTPHelper(),
$server->getNotificationManager(),
$uid
);
});

24
apps/files_sharing/lib/external/manager.php

@ -28,6 +28,7 @@ namespace OCA\Files_Sharing\External;
use OC\Files\Filesystem;
use OCP\Files;
use OC\Notification\IManager;
class Manager {
const STORAGE = '\OCA\Files_Sharing\External\Storage';
@ -57,20 +58,27 @@ class Manager {
*/
private $httpHelper;
/**
* @var IManager
*/
private $notificationManager;
/**
* @param \OCP\IDBConnection $connection
* @param \OC\Files\Mount\Manager $mountManager
* @param \OCP\Files\Storage\IStorageFactory $storageLoader
* @param \OC\HTTPHelper $httpHelper
* @param IManager $notificationManager
* @param string $uid
*/
public function __construct(\OCP\IDBConnection $connection, \OC\Files\Mount\Manager $mountManager,
\OCP\Files\Storage\IStorageFactory $storageLoader, \OC\HTTPHelper $httpHelper, $uid) {
\OCP\Files\Storage\IStorageFactory $storageLoader, \OC\HTTPHelper $httpHelper, IManager $notificationManager, $uid) {
$this->connection = $connection;
$this->mountManager = $mountManager;
$this->storageLoader = $storageLoader;
$this->httpHelper = $httpHelper;
$this->uid = $uid;
$this->notificationManager = $notificationManager;
}
/**
@ -206,6 +214,7 @@ class Manager {
$acceptShare->execute(array(1, $mountPoint, $hash, $id, $this->uid));
$this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'accept');
$this->scrapNotification($share['remote_id']);
return true;
}
@ -228,12 +237,24 @@ class Manager {
$removeShare->execute(array($id, $this->uid));
$this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'decline');
$this->scrapNotification($share['remote_id']);
return true;
}
return false;
}
/**
* @param int $remoteShare
*/
protected function scrapNotification($remoteShare) {
$filter = $this->notificationManager->createNotification();
$filter->setApp('files_sharing')
->setUser($this->uid)
->setObject('remote_share', (int) $remoteShare);
$this->notificationManager->markProcessed($filter);
}
/**
* inform remote server whether server-to-server share was accepted/declined
*
@ -265,6 +286,7 @@ class Manager {
\OC\Files\Filesystem::getMountManager(),
\OC\Files\Filesystem::getLoader(),
\OC::$server->getHTTPHelper(),
\OC::$server->getNotificationManager(),
$params['user']
);

1
apps/files_sharing/lib/hooks.php

@ -33,6 +33,7 @@ class Hooks {
\OC\Files\Filesystem::getMountManager(),
\OC\Files\Filesystem::getLoader(),
\OC::$server->getHTTPHelper(),
\OC::$server->getNotificationManager(),
$params['uid']);
$manager->removeUserShares($params['uid']);

86
apps/files_sharing/lib/notifier.php

@ -0,0 +1,86 @@
<?php
/**
* @author Joas Schilling <nickvergessen@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @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 <http://www.gnu.org/licenses/>
*
*/
namespace OCA\Files_Sharing;
use OC\Notification\INotification;
use OC\Notification\INotifier;
class Notifier implements INotifier {
/** @var \OCP\L10N\IFactory */
protected $factory;
/**
* @param \OCP\L10N\IFactory $factory
*/
public function __construct(\OCP\L10N\IFactory $factory) {
$this->factory = $factory;
}
/**
* @param INotification $notification
* @param string $languageCode The code of the language that should be used to prepare the notification
* @return INotification
*/
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('files_sharing', $languageCode);
switch ($notification->getSubject()) {
// Deal with known subjects
case 'remote_share':
$params = $notification->getSubjectParameters();
$notification->setParsedSubject(
(string) $l->t('You received %s as a remote share from %s', $params)
);
// 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;
default:
// Unknown subject => Unknown notification => throw
throw new \InvalidArgumentException();
}
}
}

1
apps/files_sharing/tests/external/managertest.php

@ -50,6 +50,7 @@ class ManagerTest extends TestCase {
$this->mountManager,
new StorageFactory(),
$httpHelper,
\OC::$server->getNotificationManager(),
$this->uid
);
}

1
apps/files_sharing/tests/server2server.php

@ -154,6 +154,7 @@ class Test_Files_Sharing_S2S_OCS_API extends TestCase {
\OC\Files\Filesystem::getMountManager(),
\OC\Files\Filesystem::getLoader(),
\OC::$server->getHTTPHelper(),
\OC::$server->getNotificationManager(),
$toDelete
);

167
lib/private/notification/action.php

@ -0,0 +1,167 @@
<?php
/**
* @author Joas Schilling <nickvergessen@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @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 <http://www.gnu.org/licenses/>
*
*/
namespace OC\Notification;
class Action implements IAction {
/** @var string */
protected $label;
/** @var string */
protected $labelParsed;
/** @var string */
protected $link;
/** @var string */
protected $requestType;
/** @var string */
protected $icon;
/**
* Constructor
*/
public function __construct() {
$this->label = '';
$this->labelParsed = '';
$this->link = '';
$this->requestType = '';
$this->icon = '';
}
/**
* @param string $label
* @return $this
* @throws \InvalidArgumentException if the label is invalid
* @since 8.2.0
*/
public function setLabel($label) {
if (!is_string($label) || $label === '' || isset($label[32])) {
throw new \InvalidArgumentException('The given label is invalid');
}
$this->label = $label;
return $this;
}
/**
* @return string
* @since 8.2.0
*/
public function getLabel() {
return $this->label;
}
/**
* @param string $label
* @return $this
* @throws \InvalidArgumentException if the label is invalid
* @since 8.2.0
*/
public function setParsedLabel($label) {
if (!is_string($label) || $label === '') {
throw new \InvalidArgumentException('The given parsed label is invalid');
}
$this->labelParsed = $label;
return $this;
}
/**
* @return string
* @since 8.2.0
*/
public function getParsedLabel() {
return $this->labelParsed;
}
/**
* @param string $link
* @param string $requestType
* @return $this
* @throws \InvalidArgumentException if the link is invalid
* @since 8.2.0
*/
public function setLink($link, $requestType) {
if (!is_string($link) || $link === '' || isset($link[256])) {
throw new \InvalidArgumentException('The given link is invalid');
}
if (!in_array($requestType, ['GET', 'POST', 'PUT', 'DELETE'], true)) {
throw new \InvalidArgumentException('The given request type is invalid');
}
$this->link = $link;
$this->requestType = $requestType;
return $this;
}
/**
* @return string
* @since 8.2.0
*/
public function getLink() {
return $this->link;
}
/**
* @return string
* @since 8.2.0
*/
public function getRequestType() {
return $this->requestType;
}
/**
* @param string $icon
* @return $this
* @throws \InvalidArgumentException if the icon is invalid
* @since 8.2.0
*/
public function setIcon($icon) {
if (!is_string($icon) || $icon === '' || isset($icon[64])) {
throw new \InvalidArgumentException('The given icon is invalid');
}
$this->icon = $icon;
return $this;
}
/**
* @return string
* @since 8.2.0
*/
public function getIcon() {
return $this->icon;
}
/**
* @return bool
*/
public function isValid() {
return $this->label !== '' && $this->link !== '';
}
/**
* @return bool
*/
public function isValidParsed() {
return $this->labelParsed !== '' && $this->link !== '';
}
}

109
lib/private/notification/iaction.php

@ -0,0 +1,109 @@
<?php
/**
* @author Joas Schilling <nickvergessen@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @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 <http://www.gnu.org/licenses/>
*
*/
namespace OC\Notification;
/**
* Interface IAction
*
* @package OC\Notification
* @since 8.2.0
*
* DEVELOPER NOTE:
* The notification api is experimental only in 8.2.0! Do not start using it,
* if you can not prepare an update for the next version afterwards.
*/
interface IAction {
/**
* @param string $label
* @return $this
* @throws \InvalidArgumentException if the label is invalid
* @since 8.2.0
*/
public function setLabel($label);
/**
* @return string
* @since 8.2.0
*/
public function getLabel();
/**
* @param string $label
* @return $this
* @throws \InvalidArgumentException if the label is invalid
* @since 8.2.0
*/
public function setParsedLabel($label);
/**
* @return string
* @since 8.2.0
*/
public function getParsedLabel();
/**
* @param string $link
* @param string $requestType
* @return $this
* @throws \InvalidArgumentException if the link is invalid
* @since 8.2.0
*/
public function setLink($link, $requestType);
/**
* @return string
* @since 8.2.0
*/
public function getLink();
/**
* @return string
* @since 8.2.0
*/
public function getRequestType();
/**
* @param string $icon
* @return $this
* @throws \InvalidArgumentException if the icon is invalid
* @since 8.2.0
*/
public function setIcon($icon);
/**
* @return string
* @since 8.2.0
*/
public function getIcon();
/**
* @return bool
* @since 8.2.0
*/
public function isValid();
/**
* @return bool
* @since 8.2.0
*/
public function isValidParsed();
}

56
lib/private/notification/iapp.php

@ -0,0 +1,56 @@
<?php
/**
* @author Joas Schilling <nickvergessen@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @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 <http://www.gnu.org/licenses/>
*
*/
namespace OC\Notification;
/**
* Interface IApp
*
* @package OC\Notification
* @since 8.2.0
*
* DEVELOPER NOTE:
* The notification api is experimental only in 8.2.0! Do not start using it,
* if you can not prepare an update for the next version afterwards.
*/
interface IApp {
/**
* @param INotification $notification
* @return null
* @throws \InvalidArgumentException When the notification is not valid
* @since 8.2.0
*/
public function notify(INotification $notification);
/**
* @param INotification $notification
* @return null
* @since 8.2.0
*/
public function markProcessed(INotification $notification);
/**
* @param INotification $notification
* @return int
* @since 8.2.0
*/
public function getCount(INotification $notification);
}

56
lib/private/notification/imanager.php

@ -0,0 +1,56 @@
<?php
/**
* @author Joas Schilling <nickvergessen@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @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 <http://www.gnu.org/licenses/>
*
*/
namespace OC\Notification;
/**
* Interface IManager
*
* @package OC\Notification
* @since 8.2.0
*
* DEVELOPER NOTE:
* The notification api is experimental only in 8.2.0! Do not start using it,
* if you can not prepare an update for the next version afterwards.
*/
interface IManager extends IApp, INotifier {
/**
* @param \Closure $service The service must implement IApp, otherwise a
* \InvalidArgumentException is thrown later
* @return null
* @since 8.2.0
*/
public function registerApp(\Closure $service);
/**
* @param \Closure $service The service must implement INotifier, otherwise a
* \InvalidArgumentException is thrown later
* @return null
* @since 8.2.0
*/
public function registerNotifier(\Closure $service);
/**
* @return INotification
* @since 8.2.0
*/
public function createNotification();
}

241
lib/private/notification/inotification.php

@ -0,0 +1,241 @@
<?php
/**
* @author Joas Schilling <nickvergessen@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @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 <http://www.gnu.org/licenses/>
*
*/
namespace OC\Notification;
/**
* Interface INotification
*
* @package OC\Notification
* @since 8.2.0
*
* DEVELOPER NOTE:
* The notification api is experimental only in 8.2.0! Do not start using it,
* if you can not prepare an update for the next version afterwards.
*/
interface INotification {
/**
* @param string $app
* @return $this
* @throws \InvalidArgumentException if the app id are invalid
* @since 8.2.0
*/
public function setApp($app);
/**
* @return string
* @since 8.2.0
*/
public function getApp();
/**
* @param string $user
* @return $this
* @throws \InvalidArgumentException if the user id are invalid
* @since 8.2.0
*/
public function setUser($user);
/**
* @return string
* @since 8.2.0
*/
public function getUser();
/**
* @param int $timestamp
* @return $this
* @throws \InvalidArgumentException if the timestamp are invalid
* @since 8.2.0
*/
public function setTimestamp($timestamp);
/**
* @return int
* @since 8.2.0
*/
public function getTimestamp();
/**
* @param string $type
* @param int $id
* @return $this
* @throws \InvalidArgumentException if the object type or id are invalid
* @since 8.2.0
*/
public function setObject($type, $id);
/**
* @return string
* @since 8.2.0
*/
public function getObjectType();
/**
* @return int
* @since 8.2.0
*/
public function getObjectId();
/**
* @param string $subject
* @param array $parameters
* @return $this
* @throws \InvalidArgumentException if the subject or parameters are invalid
* @since 8.2.0
*/
public function setSubject($subject, array $parameters = []);
/**
* @return string
* @since 8.2.0
*/
public function getSubject();
/**
* @return string[]
* @since 8.2.0
*/
public function getSubjectParameters();
/**
* @param string $subject
* @return $this
* @throws \InvalidArgumentException if the subject are invalid
* @since 8.2.0
*/
public function setParsedSubject($subject);
/**
* @return string
* @since 8.2.0
*/
public function getParsedSubject();
/**
* @param string $message
* @param array $parameters
* @return $this
* @throws \InvalidArgumentException if the message or parameters are invalid
* @since 8.2.0
*/
public function setMessage($message, array $parameters = []);
/**
* @return string
* @since 8.2.0
*/
public function getMessage();
/**
* @return string[]
* @since 8.2.0
*/
public function getMessageParameters();
/**
* @param string $message
* @return $this
* @throws \InvalidArgumentException if the message are invalid
* @since 8.2.0
*/
public function setParsedMessage($message);
/**
* @return string
* @since 8.2.0
*/
public function getParsedMessage();
/**
* @param string $link
* @return $this
* @throws \InvalidArgumentException if the link are invalid
* @since 8.2.0
*/
public function setLink($link);
/**
* @return string
* @since 8.2.0
*/
public function getLink();
/**
* @param string $icon
* @return $this
* @throws \InvalidArgumentException if the icon are invalid
* @since 8.2.0
*/
public function setIcon($icon);
/**
* @return string
* @since 8.2.0
*/
public function getIcon();
/**
* @return IAction
* @since 8.2.0
*/
public function createAction();
/**
* @param IAction $action
* @return $this
* @throws \InvalidArgumentException if the action are invalid
* @since 8.2.0
*/
public function addAction(IAction $action);
/**
* @return IAction[]
* @since 8.2.0
*/
public function getActions();
/**
* @param IAction $action
* @return $this
* @throws \InvalidArgumentException if the action are invalid
* @since 8.2.0
*/
public function addParsedAction(IAction $action);
/**
* @return IAction[]
* @since 8.2.0
*/
public function getParsedActions();
/**
* @return bool
* @since 8.2.0
*/
public function isValid();
/**
* @return bool
* @since 8.2.0
*/
public function isValidParsed();
}

43
lib/private/notification/inotifier.php

@ -0,0 +1,43 @@
<?php
/**
* @author Joas Schilling <nickvergessen@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @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 <http://www.gnu.org/licenses/>
*
*/
namespace OC\Notification;
/**
* Interface INotifier
*
* @package OC\Notification
* @since 8.2.0
*
* DEVELOPER NOTE:
* The notification api is experimental only in 8.2.0! Do not start using it,
* if you can not prepare an update for the next version afterwards.
*/
interface INotifier {
/**
* @param INotification $notification
* @param string $languageCode The code of the language that should be used to prepare the notification
* @return INotification
* @throws \InvalidArgumentException When the notification was not prepared by a notifier
* @since 8.2.0
*/
public function prepare(INotification $notification, $languageCode);
}

191
lib/private/notification/manager.php

@ -0,0 +1,191 @@
<?php
/**
* @author Joas Schilling <nickvergessen@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @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 <http://www.gnu.org/licenses/>
*
*/
namespace OC\Notification;
class Manager implements IManager {
/** @var IApp */
protected $apps;
/** @var INotifier */
protected $notifiers;
/** @var \Closure */
protected $appsClosures;
/** @var \Closure */
protected $notifiersClosures;
public function __construct() {
$this->apps = [];
$this->notifiers = [];
$this->appsClosures = [];
$this->notifiersClosures = [];
}
/**
* @param \Closure $service The service must implement IApp, otherwise a
* \InvalidArgumentException is thrown later
* @return null
* @since 8.2.0
*/
public function registerApp(\Closure $service) {
$this->appsClosures[] = $service;
$this->apps = [];
}
/**
* @param \Closure $service The service must implement INotifier, otherwise a
* \InvalidArgumentException is thrown later
* @return null
* @since 8.2.0
*/
public function registerNotifier(\Closure $service) {
$this->notifiersClosures[] = $service;
$this->notifiers = [];
}
/**
* @return IApp[]
*/
protected function getApps() {
if (!empty($this->apps)) {
return $this->apps;
}
$this->apps = [];
foreach ($this->appsClosures as $closure) {
$app = $closure();
if (!($app instanceof IApp)) {
throw new \InvalidArgumentException('The given notification app does not implement the IApp interface');
}
$this->apps[] = $app;
}
return $this->apps;
}
/**
* @return INotifier[]
*/
protected function getNotifiers() {
if (!empty($this->notifiers)) {
return $this->notifiers;
}
$this->notifiers = [];
foreach ($this->notifiersClosures as $closure) {
$notifier = $closure();
if (!($notifier instanceof INotifier)) {
throw new \InvalidArgumentException('The given notification app does not implement the INotifier interface');
}
$this->notifiers[] = $notifier;
}
return $this->notifiers;
}
/**
* @return INotification
* @since 8.2.0
*/
public function createNotification() {
return new Notification();
}
/**
* @param INotification $notification
* @return null
* @throws \InvalidArgumentException When the notification is not valid
* @since 8.2.0
*/
public function notify(INotification $notification) {
if (!$notification->isValid()) {
throw new \InvalidArgumentException('The given notification is invalid');
}
$apps = $this->getApps();
foreach ($apps as $app) {
try {
$app->notify($notification);
} catch (\InvalidArgumentException $e) {
}
}
}
/**
* @param INotification $notification
* @param string $languageCode The code of the language that should be used to prepare the notification
* @return INotification
* @throws \InvalidArgumentException When the notification was not prepared by a notifier
* @since 8.2.0
*/
public function prepare(INotification $notification, $languageCode) {
$notifiers = $this->getNotifiers();
foreach ($notifiers as $notifier) {
try {
$notification = $notifier->prepare($notification, $languageCode);
} catch (\InvalidArgumentException $e) {
continue;
}
if (!($notification instanceof INotification) || !$notification->isValidParsed()) {
throw new \InvalidArgumentException('The given notification has not been handled');
}
}
if (!($notification instanceof INotification) || !$notification->isValidParsed()) {
throw new \InvalidArgumentException('The given notification has not been handled');
}
return $notification;
}
/**
* @param INotification $notification
* @return null
*/
public function markProcessed(INotification $notification) {
$apps = $this->getApps();
foreach ($apps as $app) {
$app->markProcessed($notification);
}
}
/**
* @param INotification $notification
* @return int
*/
public function getCount(INotification $notification) {
$apps = $this->getApps();
$count = 0;
foreach ($apps as $app) {
$count += $app->getCount($notification);
}
return $count;
}
}

446
lib/private/notification/notification.php

@ -0,0 +1,446 @@
<?php
/**
* @author Joas Schilling <nickvergessen@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @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 <http://www.gnu.org/licenses/>
*
*/
namespace OC\Notification;
class Notification implements INotification {
/** @var string */
protected $app;
/** @var string */
protected $user;
/** @var int */
protected $timestamp;
/** @var string */
protected $objectType;
/** @var int */
protected $objectId;
/** @var string */
protected $subject;
/** @var array */
protected $subjectParameters;
/** @var string */
protected $subjectParsed;
/** @var string */
protected $message;
/** @var array */
protected $messageParameters;
/** @var string */
protected $messageParsed;
/** @var string */
protected $link;
/** @var string */
protected $icon;
/** @var array */
protected $actions;
/** @var array */
protected $actionsParsed;
/**
* Constructor
*/
public function __construct() {
$this->app = '';
$this->user = '';
$this->timestamp = 0;
$this->objectType = '';
$this->objectId = 0;
$this->subject = '';
$this->subjectParameters = [];
$this->subjectParsed = '';
$this->message = '';
$this->messageParameters = [];
$this->messageParsed = '';
$this->link = '';
$this->icon = '';
$this->actions = [];
$this->actionsParsed = [];
}
/**
* @param string $app
* @return $this
* @throws \InvalidArgumentException if the app id is invalid
* @since 8.2.0
*/
public function setApp($app) {
if (!is_string($app) || $app === '' || isset($app[32])) {
throw new \InvalidArgumentException('The given app name is invalid');
}
$this->app = $app;
return $this;
}
/**
* @return string
* @since 8.2.0
*/
public function getApp() {
return $this->app;
}
/**
* @param string $user
* @return $this
* @throws \InvalidArgumentException if the user id is invalid
* @since 8.2.0
*/
public function setUser($user) {
if (!is_string($user) || $user === '' || isset($user[64])) {
throw new \InvalidArgumentException('The given user id is invalid');
}
$this->user = $user;
return $this;
}
/**
* @return string
* @since 8.2.0
*/
public function getUser() {
return $this->user;
}
/**
* @param int $timestamp
* @return $this
* @throws \InvalidArgumentException if the timestamp is invalid
* @since 8.2.0
*/
public function setTimestamp($timestamp) {
if (!is_int($timestamp)) {
throw new \InvalidArgumentException('The given timestamp is invalid');
}
$this->timestamp = $timestamp;
return $this;
}
/**
* @return int
* @since 8.2.0
*/
public function getTimestamp() {
return $this->timestamp;
}
/**
* @param string $type
* @param int $id
* @return $this
* @throws \InvalidArgumentException if the object type or id is invalid
* @since 8.2.0
*/
public function setObject($type, $id) {
if (!is_string($type) || $type === '' || isset($type[64])) {
throw new \InvalidArgumentException('The given object type is invalid');
}
$this->objectType = $type;
if (!is_int($id)) {
throw new \InvalidArgumentException('The given object id is invalid');
}
$this->objectId = $id;
return $this;
}
/**
* @return string
* @since 8.2.0
*/
public function getObjectType() {
return $this->objectType;
}
/**
* @return int
* @since 8.2.0
*/
public function getObjectId() {
return $this->objectId;
}
/**
* @param string $subject
* @param array $parameters
* @return $this
* @throws \InvalidArgumentException if the subject or parameters are invalid
* @since 8.2.0
*/
public function setSubject($subject, array $parameters = []) {
if (!is_string($subject) || $subject === '' || isset($subject[64])) {
throw new \InvalidArgumentException('The given subject is invalid');
}
$this->subject = $subject;
if (!is_array($parameters)) {
throw new \InvalidArgumentException('The given subject parameters are invalid');
}
$this->subjectParameters = $parameters;
return $this;
}
/**
* @return string
* @since 8.2.0
*/
public function getSubject() {
return $this->subject;
}
/**
* @return string[]
* @since 8.2.0
*/
public function getSubjectParameters() {
return $this->subjectParameters;
}
/**
* @param string $subject
* @return $this
* @throws \InvalidArgumentException if the subject are invalid
* @since 8.2.0
*/
public function setParsedSubject($subject) {
if (!is_string($subject) || $subject === '') {
throw new \InvalidArgumentException('The given parsed subject is invalid');
}
$this->subjectParsed = $subject;
return $this;
}
/**
* @return string
* @since 8.2.0
*/
public function getParsedSubject() {
return $this->subjectParsed;
}
/**
* @param string $message
* @param array $parameters
* @return $this
* @throws \InvalidArgumentException if the message or parameters are invalid
* @since 8.2.0
*/
public function setMessage($message, array $parameters = []) {
if (!is_string($message) || $message === '' || isset($message[64])) {
throw new \InvalidArgumentException('The given message is invalid');
}
$this->message = $message;
if (!is_array($parameters)) {
throw new \InvalidArgumentException('The given message parameters are invalid');
}
$this->messageParameters = $parameters;
return $this;
}
/**
* @return string
* @since 8.2.0
*/
public function getMessage() {
return $this->message;
}
/**
* @return string[]
* @since 8.2.0
*/
public function getMessageParameters() {
return $this->messageParameters;
}
/**
* @param string $message
* @return $this
* @throws \InvalidArgumentException if the message are invalid
* @since 8.2.0
*/
public function setParsedMessage($message) {
if (!is_string($message) || $message === '') {
throw new \InvalidArgumentException('The given parsed message is invalid');
}
$this->messageParsed = $message;
return $this;
}
/**
* @return string
* @since 8.2.0
*/
public function getParsedMessage() {
return $this->messageParsed;
}
/**
* @param string $link
* @return $this
* @throws \InvalidArgumentException if the link are invalid
* @since 8.2.0
*/
public function setLink($link) {
if (!is_string($link) || $link === '' || isset($link[4000])) {
throw new \InvalidArgumentException('The given link is invalid');
}
$this->link = $link;
return $this;
}
/**
* @return string
* @since 8.2.0
*/
public function getLink() {
return $this->link;
}
/**
* @param string $icon
* @return $this
* @throws \InvalidArgumentException if the icon are invalid
* @since 8.2.0
*/
public function setIcon($icon) {
if (!is_string($icon) || $icon === '' || isset($icon[64])) {
throw new \InvalidArgumentException('The given icon is invalid');
}
$this->icon = $icon;
return $this;
}
/**
* @return string
* @since 8.2.0
*/
public function getIcon() {
return $this->icon;
}
/**
* @return IAction
* @since 8.2.0
*/
public function createAction() {
return new Action();
}
/**
* @param IAction $action
* @return $this
* @throws \InvalidArgumentException if the action are invalid
* @since 8.2.0
*/
public function addAction(IAction $action) {
if (!$action->isValid()) {
throw new \InvalidArgumentException('The given action is invalid');
}
$this->actions[] = $action;
return $this;
}
/**
* @return IAction[]
* @since 8.2.0
*/
public function getActions() {
return $this->actions;
}
/**
* @param IAction $action
* @return $this
* @throws \InvalidArgumentException if the action are invalid
* @since 8.2.0
*/
public function addParsedAction(IAction $action) {
if (!$action->isValidParsed()) {
throw new \InvalidArgumentException('The given parsed action is invalid');
}
$this->actionsParsed[] = $action;
return $this;
}
/**
* @return IAction[]
* @since 8.2.0
*/
public function getParsedActions() {
return $this->actionsParsed;
}
/**
* @return bool
* @since 8.2.0
*/
public function isValid() {
return
$this->isValidCommon()
&&
$this->getSubject() !== ''
;
}
/**
* @return bool
* @since 8.2.0
*/
public function isValidParsed() {
return
$this->isValidCommon()
&&
$this->getParsedSubject() !== ''
;
}
/**
* @return bool
*/
protected function isValidCommon() {
return
$this->getApp() !== ''
&&
$this->getUser() !== ''
&&
$this->getTimestamp() !== 0
&&
$this->getObjectType() !== ''
&&
$this->getObjectId() !== 0
;
}
}

14
lib/private/server.php

@ -53,6 +53,7 @@ use OC\Lock\DBLockingProvider;
use OC\Lock\MemcacheLockingProvider;
use OC\Lock\NoopLockingProvider;
use OC\Mail\Mailer;
use OC\Notification\Manager;
use OC\Security\CertificateManager;
use OC\Security\Crypto;
use OC\Security\Hasher;
@ -473,6 +474,9 @@ class Server extends SimpleContainer implements IServerContainer {
$c->getDatabaseConnection()
);
});
$this->registerService('NotificationManager', function() {
return new Manager();
});
$this->registerService('CapabilitiesManager', function (Server $c) {
$manager = new \OC\CapabilitiesManager();
$manager->registerCapability(function() use ($c) {
@ -1041,6 +1045,16 @@ class Server extends SimpleContainer implements IServerContainer {
return $this->query('EventDispatcher');
}
/**
* Get the Notification Manager
*
* @return \OC\Notification\IManager
* @since 8.2.0
*/
public function getNotificationManager() {
return $this->query('NotificationManager');
}
/**
* @return \OC\Session\CryptoWrapper
*/

9
lib/public/iservercontainer.php

@ -448,7 +448,6 @@ interface IServerContainer {
*/
public function getMimeTypeLoader();
/**
* Get the EventDispatcher
*
@ -456,4 +455,12 @@ interface IServerContainer {
* @since 8.2.0
*/
public function getEventDispatcher();
/**
* Get the Notification Manager
*
* @return \OC\Notification\IManager
* @since 8.2.0
*/
public function getNotificationManager();
}

236
tests/lib/notification/actiontest.php

@ -0,0 +1,236 @@
<?php
/**
* @author Joas Schilling <nickvergessen@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @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 <http://www.gnu.org/licenses/>
*
*/
namespace Test\Notification;
use OC\Notification\Action;
use OC\Notification\IAction;
use Test\TestCase;
class ActionTest extends TestCase {
/** @var IAction */
protected $action;
public function setUp() {
parent::setUp();
$this->action = new Action();
}
public function dataSetLabel() {
return [
['test1'],
[str_repeat('a', 1)],
[str_repeat('a', 32)],
];
}
/**
* @dataProvider dataSetLabel
* @param string $label
*/
public function testSetLabel($label) {
$this->assertSame('', $this->action->getLabel());
$this->action->setLabel($label);
$this->assertSame($label, $this->action->getLabel());
}
public function dataSetLabelInvalid() {
return [
[true],
[false],
[0],
[1],
[''],
[str_repeat('a', 33)],
[[]],
[[str_repeat('a', 33)]],
];
}
/**
* @dataProvider dataSetLabelInvalid
* @param string $label
*
* @expectedException \InvalidArgumentException
*/
public function testSetLabelInvalid($label) {
$this->action->setLabel($label);
}
public function dataSetParsedLabel() {
return [
['test1'],
[str_repeat('a', 1)],
[str_repeat('a', 32)],
];
}
/**
* @dataProvider dataSetParsedLabel
* @param string $label
*/
public function testSetParsedLabel($label) {
$this->assertSame('', $this->action->getParsedLabel());
$this->action->setParsedLabel($label);
$this->assertSame($label, $this->action->getParsedLabel());
}
public function dataSetParsedLabelInvalid() {
return [
[true],
[false],
[0],
[1],
[''],
[[]],
[[str_repeat('a', 33)]],
];
}
/**
* @dataProvider dataSetParsedLabelInvalid
* @param string $label
*
* @expectedException \InvalidArgumentException
*/
public function testSetParsedLabelInvalid($label) {
$this->action->setParsedLabel($label);
}
public function dataSetLink() {
return [
['test1', 'GET'],
['test2', 'POST'],
[str_repeat('a', 1), 'PUT'],
[str_repeat('a', 256), 'DELETE'],
];
}
/**
* @dataProvider dataSetLink
* @param string $link
* @param string $type
*/
public function testSetLink($link, $type) {
$this->assertSame('', $this->action->getLink());
$this->action->setLink($link, $type);
$this->assertSame($link, $this->action->getLink());
$this->assertSame($type, $this->action->getRequestType());
}
public function dataSetLinkInvalid() {
return [
// Invalid link
[true, 'GET'],
[false, 'GET'],
[0, 'GET'],
[1, 'GET'],
['', 'GET'],
[str_repeat('a', 257), 'GET'],
[[], 'GET'],
[[str_repeat('a', 257)], 'GET'],
// Invalid type
['url', 'notGET'],
['url', true],
['url', false],
['url', 0],
['url', 1],
['url', []],
['url', ['GET']],
];
}
/**
* @dataProvider dataSetLinkInvalid
* @param string $link
* @param string $type
*
* @expectedException \InvalidArgumentException
*/
public function testSetLinkInvalid($link, $type) {
$this->action->setLink($link, $type);
}
public function dataSetIcon() {
return [
['test1'],
[str_repeat('a', 1)],
[str_repeat('a', 64)],
];
}
/**
* @dataProvider dataSetIcon
* @param string $icon
*/
public function testSetIcon($icon) {
$this->assertSame('', $this->action->getIcon());
$this->action->setIcon($icon);
$this->assertSame($icon, $this->action->getIcon());
}
public function dataSetIconInvalid() {
return [
[true],
[false],
[0],
[1],
[''],
[str_repeat('a', 65)],
[[]],
[[str_repeat('a', 65)]],
];
}
/**
* @dataProvider dataSetIconInvalid
* @param string $icon
*
* @expectedException \InvalidArgumentException
*/
public function testSetIconInvalid($icon) {
$this->action->setIcon($icon);
}
public function testIsValid() {
$this->assertFalse($this->action->isValid());
$this->assertFalse($this->action->isValidParsed());
$this->action->setLabel('label');
$this->assertFalse($this->action->isValid());
$this->assertFalse($this->action->isValidParsed());
$this->action->setLink('link', 'GET');
$this->assertTrue($this->action->isValid());
$this->assertFalse($this->action->isValidParsed());
}
public function testIsValidParsed() {
$this->assertFalse($this->action->isValid());
$this->assertFalse($this->action->isValidParsed());
$this->action->setParsedLabel('label');
$this->assertFalse($this->action->isValid());
$this->assertFalse($this->action->isValidParsed());
$this->action->setLink('link', 'GET');
$this->assertFalse($this->action->isValid());
$this->assertTrue($this->action->isValidParsed());
}
}

345
tests/lib/notification/managertest.php

@ -0,0 +1,345 @@
<?php
/**
* @author Joas Schilling <nickvergessen@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @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 <http://www.gnu.org/licenses/>
*
*/
namespace Test\Notification;
use OC\Notification\Manager;
use OC\Notification\IManager;
use Test\TestCase;
class ManagerTest extends TestCase {
/** @var IManager */
protected $manager;
public function setUp() {
parent::setUp();
$this->manager = new Manager();
}
public function testRegisterApp() {
$app = $this->getMockBuilder('OC\Notification\IApp')
->disableOriginalConstructor()
->getMock();
$closure = function() use ($app) {
return $app;
};
$this->assertEquals([], $this->invokePrivate($this->manager, 'getApps'));
$this->manager->registerApp($closure);
$this->assertEquals([$app], $this->invokePrivate($this->manager, 'getApps'));
$this->assertEquals([$app], $this->invokePrivate($this->manager, 'getApps'));
$this->manager->registerApp($closure);
$this->assertEquals([$app, $app], $this->invokePrivate($this->manager, 'getApps'));
}
/**
* @expectedException \InvalidArgumentException
*/
public function testRegisterAppInvalid() {
$notifier = $this->getMockBuilder('OC\Notification\INotifier')
->disableOriginalConstructor()
->getMock();
$closure = function() use ($notifier) {
return $notifier;
};
$this->manager->registerApp($closure);
$this->invokePrivate($this->manager, 'getApps');
}
public function testRegisterNotifier() {
$notifier = $this->getMockBuilder('OC\Notification\INotifier')
->disableOriginalConstructor()
->getMock();
$closure = function() use ($notifier) {
return $notifier;
};
$this->assertEquals([], $this->invokePrivate($this->manager, 'getNotifiers'));
$this->manager->registerNotifier($closure);
$this->assertEquals([$notifier], $this->invokePrivate($this->manager, 'getNotifiers'));
$this->assertEquals([$notifier], $this->invokePrivate($this->manager, 'getNotifiers'));
$this->manager->registerNotifier($closure);
$this->assertEquals([$notifier, $notifier], $this->invokePrivate($this->manager, 'getNotifiers'));
}
/**
* @expectedException \InvalidArgumentException
*/
public function testRegisterNotifierInvalid() {
$app = $this->getMockBuilder('OC\Notification\IApp')
->disableOriginalConstructor()
->getMock();
$closure = function() use ($app) {
return $app;
};
$this->manager->registerNotifier($closure);
$this->invokePrivate($this->manager, 'getNotifiers');
}
public function testCreateNotification() {
$action = $this->manager->createNotification();
$this->assertInstanceOf('OC\Notification\INotification', $action);
}
public function testNotify() {
/** @var \OC\Notification\INotification|\PHPUnit_Framework_MockObject_MockObject $notification */
$notification = $this->getMockBuilder('OC\Notification\INotification')
->disableOriginalConstructor()
->getMock();
$notification->expects($this->once())
->method('isValid')
->willReturn(true);
/** @var \OC\Notification\IApp|\PHPUnit_Framework_MockObject_MockObject $app */
$app = $this->getMockBuilder('OC\Notification\IApp')
->disableOriginalConstructor()
->getMock();
$app->expects($this->once())
->method('notify')
->with($notification);
/** @var \OC\Notification\IApp|\PHPUnit_Framework_MockObject_MockObject $app2 */
$app2 = $this->getMockBuilder('OC\Notification\IApp')
->disableOriginalConstructor()
->getMock();
$app2->expects($this->once())
->method('notify')
->with($notification);
$this->manager->registerApp(function() use ($app) {
return $app;
});
$this->manager->registerApp(function() use ($app2) {
return $app2;
});
$this->manager->notify($notification);
}
/**
* @expectedException \InvalidArgumentException
*/
public function testNotifyInvalid() {
/** @var \OC\Notification\INotification|\PHPUnit_Framework_MockObject_MockObject $notification */
$notification = $this->getMockBuilder('OC\Notification\INotification')
->disableOriginalConstructor()
->getMock();
$notification->expects($this->once())
->method('isValid')
->willReturn(false);
$this->manager->notify($notification);
}
public function testPrepare() {
/** @var \OC\Notification\INotification|\PHPUnit_Framework_MockObject_MockObject $notification */
$notification = $this->getMockBuilder('OC\Notification\INotification')
->disableOriginalConstructor()
->getMock();
$notification->expects($this->once())
->method('isValidParsed')
->willReturn(true);
/** @var \OC\Notification\INotification|\PHPUnit_Framework_MockObject_MockObject $notification2 */
$notification2 = $this->getMockBuilder('OC\Notification\INotification')
->disableOriginalConstructor()
->getMock();
$notification2->expects($this->exactly(2))
->method('isValidParsed')
->willReturn(true);
/** @var \OC\Notification\IApp|\PHPUnit_Framework_MockObject_MockObject $notifier */
$notifier = $this->getMockBuilder('OC\Notification\INotifier')
->disableOriginalConstructor()
->getMock();
$notifier->expects($this->once())
->method('prepare')
->with($notification, 'en')
->willReturnArgument(0);
/** @var \OC\Notification\IApp|\PHPUnit_Framework_MockObject_MockObject $notifier2 */
$notifier2 = $this->getMockBuilder('OC\Notification\INotifier')
->disableOriginalConstructor()
->getMock();
$notifier2->expects($this->once())
->method('prepare')
->with($notification, 'en')
->willReturn($notification2);
$this->manager->registerNotifier(function() use ($notifier) {
return $notifier;
});
$this->manager->registerNotifier(function() use ($notifier2) {
return $notifier2;
});
$this->assertEquals($notification2, $this->manager->prepare($notification, 'en'));
}
/**
* @expectedException \InvalidArgumentException
*/
public function testPrepareInvalid() {
/** @var \OC\Notification\INotification|\PHPUnit_Framework_MockObject_MockObject $notification */
$notification = $this->getMockBuilder('OC\Notification\INotification')
->disableOriginalConstructor()
->getMock();
$notification->expects($this->once())
->method('isValidParsed')
->willReturn(false);
/** @var \OC\Notification\IApp|\PHPUnit_Framework_MockObject_MockObject $notifier */
$notifier = $this->getMockBuilder('OC\Notification\INotifier')
->disableOriginalConstructor()
->getMock();
$notifier->expects($this->once())
->method('prepare')
->with($notification, 'de')
->willReturnArgument(0);
$this->manager->registerNotifier(function() use ($notifier) {
return $notifier;
});
$this->manager->prepare($notification, 'de');
}
public function testPrepareNotifierThrows() {
/** @var \OC\Notification\INotification|\PHPUnit_Framework_MockObject_MockObject $notification */
$notification = $this->getMockBuilder('OC\Notification\INotification')
->disableOriginalConstructor()
->getMock();
$notification->expects($this->once())
->method('isValidParsed')
->willReturn(true);
/** @var \OC\Notification\IApp|\PHPUnit_Framework_MockObject_MockObject $notifier */
$notifier = $this->getMockBuilder('OC\Notification\INotifier')
->disableOriginalConstructor()
->getMock();
$notifier->expects($this->once())
->method('prepare')
->with($notification, 'de')
->willThrowException(new \InvalidArgumentException);
$this->manager->registerNotifier(function() use ($notifier) {
return $notifier;
});
$this->assertEquals($notification, $this->manager->prepare($notification, 'de'));
}
/**
* @expectedException \InvalidArgumentException
*/
public function testPrepareNoNotifier() {
/** @var \OC\Notification\INotification|\PHPUnit_Framework_MockObject_MockObject $notification */
$notification = $this->getMockBuilder('OC\Notification\INotification')
->disableOriginalConstructor()
->getMock();
$notification->expects($this->once())
->method('isValidParsed')
->willReturn(false);
$this->manager->prepare($notification, 'en');
}
public function testMarkProcessed() {
/** @var \OC\Notification\INotification|\PHPUnit_Framework_MockObject_MockObject $notification */
$notification = $this->getMockBuilder('OC\Notification\INotification')
->disableOriginalConstructor()
->getMock();
/** @var \OC\Notification\IApp|\PHPUnit_Framework_MockObject_MockObject $app */
$app = $this->getMockBuilder('OC\Notification\IApp')
->disableOriginalConstructor()
->getMock();
$app->expects($this->once())
->method('markProcessed')
->with($notification);
/** @var \OC\Notification\IApp|\PHPUnit_Framework_MockObject_MockObject $app2 */
$app2 = $this->getMockBuilder('OC\Notification\IApp')
->disableOriginalConstructor()
->getMock();
$app2->expects($this->once())
->method('markProcessed')
->with($notification);
$this->manager->registerApp(function() use ($app) {
return $app;
});
$this->manager->registerApp(function() use ($app2) {
return $app2;
});
$this->manager->markProcessed($notification);
}
public function testGetCount() {
/** @var \OC\Notification\INotification|\PHPUnit_Framework_MockObject_MockObject $notification */
$notification = $this->getMockBuilder('OC\Notification\INotification')
->disableOriginalConstructor()
->getMock();
/** @var \OC\Notification\IApp|\PHPUnit_Framework_MockObject_MockObject $app */
$app = $this->getMockBuilder('OC\Notification\IApp')
->disableOriginalConstructor()
->getMock();
$app->expects($this->once())
->method('getCount')
->with($notification)
->willReturn(21);
/** @var \OC\Notification\IApp|\PHPUnit_Framework_MockObject_MockObject $app2 */
$app2 = $this->getMockBuilder('OC\Notification\IApp')
->disableOriginalConstructor()
->getMock();
$app2->expects($this->once())
->method('getCount')
->with($notification)
->willReturn(42);
$this->manager->registerApp(function() use ($app) {
return $app;
});
$this->manager->registerApp(function() use ($app2) {
return $app2;
});
$this->assertSame(63, $this->manager->getCount($notification));
}
}

601
tests/lib/notification/notificationtest.php

@ -0,0 +1,601 @@
<?php
/**
* @author Joas Schilling <nickvergessen@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @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 <http://www.gnu.org/licenses/>
*
*/
namespace Test\Notification;
use OC\Notification\Notification;
use OC\Notification\INotification;
use Test\TestCase;
class NotificationTest extends TestCase {
/** @var INotification */
protected $notification;
public function setUp() {
parent::setUp();
$this->notification = new Notification();
}
protected function dataValidString($maxLength) {
$dataSets = [
['test1'],
[str_repeat('a', 1)],
];
if ($maxLength !== false) {
$dataSets[] = [str_repeat('a', $maxLength)];
}
return $dataSets;
}
protected function dataInvalidString($maxLength) {
$dataSets = [
[true],
[false],
[0],
[1],
[''],
[[]],
];
if ($maxLength !== false) {
$dataSets[] = [str_repeat('a', $maxLength + 1)];
$dataSets[] = [[str_repeat('a', $maxLength + 1)]];
}
return $dataSets;
}
protected function dataValidInt() {
return [
[0],
[1],
[time()],
];
}
protected function dataInvalidInt() {
return [
[true],
[false],
[''],
['a'],
[str_repeat('a', 256)],
[[]],
[['a']],
[[str_repeat('a', 256)]],
];
}
public function dataSetApp() {
return $this->dataValidString(32);
}
/**
* @dataProvider dataSetApp
* @param string $app
*/
public function testSetApp($app) {
$this->assertSame('', $this->notification->getApp());
$this->notification->setApp($app);
$this->assertSame($app, $this->notification->getApp());
}
public function dataSetAppInvalid() {
return $this->dataInvalidString(32);
}
/**
* @dataProvider dataSetAppInvalid
* @param mixed $app
*
* @expectedException \InvalidArgumentException
*/
public function testSetAppInvalid($app) {
$this->notification->setApp($app);
}
public function dataSetUser() {
return $this->dataValidString(64);
}
/**
* @dataProvider dataSetUser
* @param string $user
*/
public function testSetUser($user) {
$this->assertSame('', $this->notification->getUser());
$this->notification->setUser($user);
$this->assertSame($user, $this->notification->getUser());
}
public function dataSetUserInvalid() {
return $this->dataInvalidString(64);
}
/**
* @dataProvider dataSetUserInvalid
* @param mixed $user
*
* @expectedException \InvalidArgumentException
*/
public function testSetUserInvalid($user) {
$this->notification->setUser($user);
}
public function dataSetTimestamp() {
return $this->dataValidInt();
}
/**
* @dataProvider dataSetTimestamp
* @param int $timestamp
*/
public function testSetTimestamp($timestamp) {
$this->assertSame(0, $this->notification->getTimestamp());
$this->notification->setTimestamp($timestamp);
$this->assertSame($timestamp, $this->notification->getTimestamp());
}
public function dataSetTimestampInvalid() {
return $this->dataInvalidInt();
}
/**
* @dataProvider dataSetTimestampInvalid
* @param mixed $timestamp
*
* @expectedException \InvalidArgumentException
*/
public function testSetTimestampInvalid($timestamp) {
$this->notification->setTimestamp($timestamp);
}
public function dataSetObject() {
return [
['a', 1],
[str_repeat('a', 64), time()],
];
}
/**
* @dataProvider dataSetObject
* @param string $type
* @param int $id
*/
public function testSetObject($type, $id) {
$this->assertSame('', $this->notification->getObjectType());
$this->assertSame(0, $this->notification->getObjectId());
$this->notification->setObject($type, $id);
$this->assertSame($type, $this->notification->getObjectType());
$this->assertSame($id, $this->notification->getObjectId());
}
public function dataSetObjectTypeInvalid() {
return $this->dataInvalidString(64);
}
/**
* @dataProvider dataSetObjectTypeInvalid
* @param mixed $type
*
* @expectedException \InvalidArgumentException
* @expectedMessage 'The given object type is invalid'
*/
public function testSetObjectTypeInvalid($type) {
$this->notification->setObject($type, 1337);
}
public function dataSetObjectIdInvalid() {
return $this->dataInvalidInt();
}
/**
* @dataProvider dataSetObjectIdInvalid
* @param mixed $id
*
* @expectedException \InvalidArgumentException
* @expectedMessage 'The given object id is invalid'
*/
public function testSetObjectIdInvalid($id) {
$this->notification->setObject('object', $id);
}
public function dataSetSubject() {
return [
['a', []],
[str_repeat('a', 64), [str_repeat('a', 160)]],
[str_repeat('a', 64), array_fill(0, 160, 'a')],
];
}
/**
* @dataProvider dataSetSubject
* @param string $subject
* @param array $parameters
*/
public function testSetSubject($subject, $parameters) {
$this->assertSame('', $this->notification->getSubject());
$this->assertSame([], $this->notification->getSubjectParameters());
$this->notification->setSubject($subject, $parameters);
$this->assertSame($subject, $this->notification->getSubject());
$this->assertSame($parameters, $this->notification->getSubjectParameters());
}
public function dataSetSubjectInvalidSubject() {
return $this->dataInvalidString(64);
}
/**
* @dataProvider dataSetSubjectInvalidSubject
* @param mixed $subject
*
* @expectedException \InvalidArgumentException
*/
public function testSetSubjectInvalidSubject($subject) {
$this->notification->setSubject($subject, []);
}
public function dataSetParsedSubject() {
return $this->dataValidString(false);
}
/**
* @dataProvider dataSetParsedSubject
* @param string $subject
*/
public function testSetParsedSubject($subject) {
$this->assertSame('', $this->notification->getParsedSubject());
$this->notification->setParsedSubject($subject);
$this->assertSame($subject, $this->notification->getParsedSubject());
}
public function dataSetParsedSubjectInvalid() {
return $this->dataInvalidString(false);
}
/**
* @dataProvider dataSetParsedSubjectInvalid
* @param mixed $subject
*
* @expectedException \InvalidArgumentException
*/
public function testSetParsedSubjectInvalid($subject) {
$this->notification->setParsedSubject($subject);
}
public function dataSetMessage() {
return [
['a', []],
[str_repeat('a', 64), [str_repeat('a', 160)]],
[str_repeat('a', 64), array_fill(0, 160, 'a')],
];
}
/**
* @dataProvider dataSetMessage
* @param string $message
* @param array $parameters
*/
public function testSetMessage($message, $parameters) {
$this->assertSame('', $this->notification->getMessage());
$this->assertSame([], $this->notification->getMessageParameters());
$this->notification->setMessage($message, $parameters);
$this->assertSame($message, $this->notification->getMessage());
$this->assertSame($parameters, $this->notification->getMessageParameters());
}
public function dataSetMessageInvalidMessage() {
return $this->dataInvalidString(64);
}
/**
* @dataProvider dataSetMessageInvalidMessage
* @param mixed $message
*
* @expectedException \InvalidArgumentException
*/
public function testSetMessageInvalidMessage($message) {
$this->notification->setMessage($message, []);
}
public function dataSetParsedMessage() {
return $this->dataValidString(false);
}
/**
* @dataProvider dataSetParsedMessage
* @param string $message
*/
public function testSetParsedMessage($message) {
$this->assertSame('', $this->notification->getParsedMessage());
$this->notification->setParsedMessage($message);
$this->assertSame($message, $this->notification->getParsedMessage());
}
public function dataSetParsedMessageInvalid() {
return $this->dataInvalidString(false);
}
/**
* @dataProvider dataSetParsedMessageInvalid
* @param mixed $message
*
* @expectedException \InvalidArgumentException
*/
public function testSetParsedMessageInvalid($message) {
$this->notification->setParsedMessage($message);
}
public function dataSetLink() {
return $this->dataValidString(4000);
}
/**
* @dataProvider dataSetLink
* @param string $link
*/
public function testSetLink($link) {
$this->assertSame('', $this->notification->getLink());
$this->notification->setLink($link);
$this->assertSame($link, $this->notification->getLink());
}
public function dataSetLinkInvalid() {
return $this->dataInvalidString(4000);
}
/**
* @dataProvider dataSetLinkInvalid
* @param mixed $link
*
* @expectedException \InvalidArgumentException
*/
public function testSetLinkInvalid($link) {
$this->notification->setLink($link);
}
public function dataSetIcon() {
return $this->dataValidString(64);
}
/**
* @dataProvider dataSetIcon
* @param string $icon
*/
public function testSetIcon($icon) {
$this->assertSame('', $this->notification->getIcon());
$this->notification->setIcon($icon);
$this->assertSame($icon, $this->notification->getIcon());
}
public function dataSetIconInvalid() {
return $this->dataInvalidString(64);
}
/**
* @dataProvider dataSetIconInvalid
* @param mixed $icon
*
* @expectedException \InvalidArgumentException
*/
public function testSetIconInvalid($icon) {
$this->notification->setIcon($icon);
}
public function testCreateAction() {
$action = $this->notification->createAction();
$this->assertInstanceOf('OC\Notification\IAction', $action);
}
public function testAddAction() {
/** @var \OC\Notification\IAction|\PHPUnit_Framework_MockObject_MockObject $action */
$action = $this->getMockBuilder('OC\Notification\IAction')
->disableOriginalConstructor()
->getMock();
$action->expects($this->once())
->method('isValid')
->willReturn(true);
$action->expects($this->never())
->method('isValidParsed');
$this->notification->addAction($action);
$this->assertEquals([$action], $this->notification->getActions());
$this->assertEquals([], $this->notification->getParsedActions());
}
/**
* @expectedException \InvalidArgumentException
*/
public function testAddActionInvalid() {
/** @var \OC\Notification\IAction|\PHPUnit_Framework_MockObject_MockObject $action */
$action = $this->getMockBuilder('OC\Notification\IAction')
->disableOriginalConstructor()
->getMock();
$action->expects($this->once())
->method('isValid')
->willReturn(false);
$action->expects($this->never())
->method('isValidParsed');
$this->notification->addAction($action);
}
public function testAddParsedAction() {
/** @var \OC\Notification\IAction|\PHPUnit_Framework_MockObject_MockObject $action */
$action = $this->getMockBuilder('OC\Notification\IAction')
->disableOriginalConstructor()
->getMock();
$action->expects($this->once())
->method('isValidParsed')
->willReturn(true);
$action->expects($this->never())
->method('isValid');
$this->notification->addParsedAction($action);
$this->assertEquals([$action], $this->notification->getParsedActions());
$this->assertEquals([], $this->notification->getActions());
}
/**
* @expectedException \InvalidArgumentException
*/
public function testAddParsedActionInvalid() {
/** @var \OC\Notification\IAction|\PHPUnit_Framework_MockObject_MockObject $action */
$action = $this->getMockBuilder('OC\Notification\IAction')
->disableOriginalConstructor()
->getMock();
$action->expects($this->once())
->method('isValidParsed')
->willReturn(false);
$action->expects($this->never())
->method('isValid');
$this->notification->addParsedAction($action);
}
public function dataIsValid() {
return [
[false, '', false],
[true, '', false],
[false, 'a', false],
[true, 'a', true],
];
}
/**
* @dataProvider dataIsValid
*
* @param bool $isValidCommon
* @param string $subject
* @param bool $expected
*/
public function testIsValid($isValidCommon, $subject, $expected) {
/** @var \OC\Notification\INotification|\PHPUnit_Framework_MockObject_MockObject $notification */
$notification = $this->getMockBuilder('\OC\Notification\Notification')
->setMethods([
'isValidCommon',
'getSubject',
])
->getMock();
$notification->expects($this->once())
->method('isValidCommon')
->willReturn($isValidCommon);
$notification->expects(!$isValidCommon ? $this->never() : $this->once())
->method('getSubject')
->willReturn($subject);
$notification->expects($this->never())
->method('getParsedSubject')
->willReturn($subject);
$this->assertEquals($expected, $notification->isValid());
}
/**
* @dataProvider dataIsValid
*
* @param bool $isValidCommon
* @param string $subject
* @param bool $expected
*/
public function testIsParsedValid($isValidCommon, $subject, $expected) {
/** @var \OC\Notification\INotification|\PHPUnit_Framework_MockObject_MockObject $notification */
$notification = $this->getMockBuilder('\OC\Notification\Notification')
->setMethods([
'isValidCommon',
'getParsedSubject',
])
->getMock();
$notification->expects($this->once())
->method('isValidCommon')
->willReturn($isValidCommon);
$notification->expects(!$isValidCommon ? $this->never() : $this->once())
->method('getParsedSubject')
->willReturn($subject);
$notification->expects($this->never())
->method('getSubject')
->willReturn($subject);
$this->assertEquals($expected, $notification->isValidParsed());
}
public function dataIsValidCommon() {
return [
['', '', 0, '', 0, false],
['app', '', 0, '', 0, false],
['app', 'user', 0, '', 0, false],
['app', 'user', time(), '', 0, false],
['app', 'user', time(), 'type', 0, false],
['app', 'user', time(), 'type', 42, true],
];
}
/**
* @dataProvider dataIsValidCommon
*
* @param string $app
* @param string $user
* @param int $timestamp
* @param string $objectType
* @param int $objectId
* @param bool $expected
*/
public function testIsValidCommon($app, $user, $timestamp, $objectType, $objectId, $expected) {
/** @var \OC\Notification\INotification|\PHPUnit_Framework_MockObject_MockObject $notification */
$notification = $this->getMockBuilder('\OC\Notification\Notification')
->setMethods([
'getApp',
'getUser',
'getTimestamp',
'getObjectType',
'getObjectId',
])
->getMock();
$notification->expects($this->any())
->method('getApp')
->willReturn($app);
$notification->expects($this->any())
->method('getUser')
->willReturn($user);
$notification->expects($this->any())
->method('getTimestamp')
->willReturn($timestamp);
$notification->expects($this->any())
->method('getObjectType')
->willReturn($objectType);
$notification->expects($this->any())
->method('getObjectId')
->willReturn($objectId);
$this->assertEquals($expected, $this->invokePrivate($notification, 'isValidCommon'));
}
}

2
tests/lib/server.php

@ -104,6 +104,8 @@ class Server extends \Test\TestCase {
['NavigationManager', '\OC\NavigationManager'],
['NavigationManager', '\OCP\INavigationManager'],
['NotificationManager', '\OC\Notification\Manager'],
['NotificationManager', '\OC\Notification\IManager'],
['UserCache', '\OC\Cache\File'],
['UserCache', '\OCP\ICache'],

Loading…
Cancel
Save