apps/files_sharing/lib/Service/NotificationPublisher.php
<?php
/**
* @author Vincent Petry <pvince81@owncloud.com>
*
* @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 <http://www.gnu.org/licenses/>
*
*/
namespace OCA\Files_Sharing\Service;
use OCP\IURLGenerator;
use OCP\IUserManager;
use OCP\IGroupManager;
use OCP\Share\IShare;
class NotificationPublisher {
/** @var \OCP\Notification\IManager */
private $notificationManager;
/** @var IGroupManager */
private $groupManager;
/** @var IUserManager */
private $userManager;
/** @var IURLGenerator */
private $urlGenerator;
public function __construct(
\OCP\Notification\IManager $notificationManager,
IUserManager $userManager,
IGroupManager $groupManager,
IURLGenerator $urlGenerator
) {
$this->notificationManager = $notificationManager;
$this->userManager = $userManager;
$this->groupManager = $groupManager;
$this->urlGenerator = $urlGenerator;
}
private function getAffectedUsers(IShare $share) {
$users = [];
if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
// notify all group members
$group = $this->groupManager->get($share->getSharedWith());
// TODO: scale / chunk / ...
foreach ($group->getUsers() as $user) {
if ($user->getUID() !== $share->getShareOwner() && $user->getUID() !== $share->getSharedBy()) {
yield $user->getUID();
}
}
} elseif ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
yield $share->getSharedWith();
}
}
/**
* Send notification for accepting share
* The notification will be sent if the share type is either user or group (not link, for example)
* and only for pending shares (if the share has a different status the notification won't be sent)
*
* @param IShare $share share
*/
public function sendNotification(IShare $share) {
if ($share->getShareType() !== \OCP\Share::SHARE_TYPE_USER &&
$share->getShareType() !== \OCP\Share::SHARE_TYPE_GROUP) {
return;
}
if ($share->getState() !== \OCP\Share::STATE_PENDING) {
return;
}
$fileLink = $this->urlGenerator->linkToRoute('files.viewcontroller.showFile', ['fileId' => $share->getNode()->getId()]);
$endpointUrl = $this->urlGenerator->linkTo('', 'ocs/v1.php/apps/files_sharing/api/v1/shares/pending/' . $share->getId());
foreach ($this->getAffectedUsers($share) as $userId) {
$notification = $this->notificationManager->createNotification();
$notification->setApp('files_sharing')
->setUser($userId)
->setDateTime(new \DateTime())
->setObject('local_share', $share->getFullId());
// the fullId is used here to be able to retrieve the share using the core's share manager
// in case we need to retrieve the share object from the notification.
// it can be used later to discard the notification if the share isn't valid any longer.
$notification->setIcon(
$this->urlGenerator->imagePath('core', 'actions/shared.svg')
);
$notification->setLink($fileLink);
$notification->setSubject('local_share', [$share->getShareOwner(), $share->getSharedBy(), $share->getNode()->getName()]);
$notification->setMessage('local_share', [$share->getShareOwner(), $share->getSharedBy(), $share->getNode()->getName()]);
$declineAction = $notification->createAction();
$declineAction->setLabel('decline');
$declineAction->setLink($endpointUrl, 'DELETE');
$notification->addAction($declineAction);
$acceptAction = $notification->createAction();
$acceptAction->setLabel('accept');
$acceptAction->setLink($endpointUrl, 'POST');
$acceptAction->setPrimary(true);
$notification->addAction($acceptAction);
$this->notificationManager->notify($notification);
}
}
/**
* Discards all notification related to the given share.
* This is useful to cancel notifications in case said share
* is being deleted
*
* @param IShare $share share
*/
public function discardNotification(IShare $share) {
foreach ($this->getAffectedUsers($share) as $userId) {
$notification = $this->notificationManager->createNotification();
$notification->setApp('files_sharing')
->setUser($userId)
->setObject('local_share', $share->getFullId());
$this->notificationManager->markProcessed($notification);
}
}
/**
* Discards the notification related to the given share for the specific user.
* This is useful to remove the notification when the user has seen or processed it
*
* @param IShare $share share
* @param string $userId the user id (who should have been received the notification) that will
* have his notification discarded.
*/
public function discardNotificationForUser(IShare $share, $userId) {
$notification = $this->notificationManager->createNotification();
$notification->setApp('files_sharing')
->setUser($userId)
->setObject('local_share', $share->getFullId());
$this->notificationManager->markProcessed($notification);
}
}