You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
325 lines
9.8 KiB
325 lines
9.8 KiB
5 years ago
|
<?php
|
||
|
/**
|
||
|
* @author Joas Schilling <coding@schilljs.com>
|
||
|
*
|
||
|
* @copyright Copyright (c) 2016, 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\Notifications;
|
||
|
|
||
|
|
||
|
use OCA\Notifications\Exceptions\NotificationNotFoundException;
|
||
|
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||
|
use OCP\IDBConnection;
|
||
|
use OCP\Notification\IAction;
|
||
|
use OCP\Notification\IManager;
|
||
|
use OCP\Notification\INotification;
|
||
|
|
||
|
class Handler {
|
||
|
/** @var IDBConnection */
|
||
|
protected $connection;
|
||
|
|
||
|
/** @var IManager */
|
||
|
protected $manager;
|
||
|
|
||
|
/**
|
||
|
* @param IDBConnection $connection
|
||
|
* @param IManager $manager
|
||
|
*/
|
||
|
public function __construct(IDBConnection $connection, IManager $manager) {
|
||
|
$this->connection = $connection;
|
||
|
$this->manager = $manager;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Add a new notification to the database
|
||
|
*
|
||
|
* @param INotification $notification
|
||
|
* @return int
|
||
|
*/
|
||
|
public function add(INotification $notification): int {
|
||
|
$sql = $this->connection->getQueryBuilder();
|
||
|
$sql->insert('notifications');
|
||
|
$this->sqlInsert($sql, $notification);
|
||
|
$sql->execute();
|
||
|
|
||
|
return $sql->getLastInsertId();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Count the notifications matching the given Notification
|
||
|
*
|
||
|
* @param INotification $notification
|
||
|
* @return int
|
||
|
*/
|
||
|
public function count(INotification $notification): int {
|
||
|
$sql = $this->connection->getQueryBuilder();
|
||
|
$sql->select($sql->createFunction('COUNT(*)'))
|
||
|
->from('notifications');
|
||
|
|
||
|
$this->sqlWhere($sql, $notification);
|
||
|
|
||
|
$statement = $sql->execute();
|
||
|
$count = (int) $statement->fetchColumn();
|
||
|
$statement->closeCursor();
|
||
|
|
||
|
return $count;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Delete the notifications matching the given Notification
|
||
|
*
|
||
|
* @param INotification $notification
|
||
|
* @return array A Map with all deleted notifications [user => [notifications]]
|
||
|
*/
|
||
|
public function delete(INotification $notification): array {
|
||
|
$sql = $this->connection->getQueryBuilder();
|
||
|
$sql->select('notification_id', 'user')
|
||
|
->from('notifications');
|
||
|
|
||
|
$this->sqlWhere($sql, $notification);
|
||
|
$statement = $sql->execute();
|
||
|
|
||
|
$deleted = [];
|
||
|
while ($row = $statement->fetch()) {
|
||
|
if (!isset($deleted[$row['user']])) {
|
||
|
$deleted[$row['user']] = [];
|
||
|
}
|
||
|
|
||
|
$deleted[$row['user']][] = (int) $row['notification_id'];
|
||
|
}
|
||
|
$statement->closeCursor();
|
||
|
|
||
|
foreach ($deleted as $user => $notifications) {
|
||
|
foreach ($notifications as $notificationId) {
|
||
|
$this->deleteById($notificationId, $user);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $deleted;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Delete the notification of a given user
|
||
|
*
|
||
|
* @param string $user
|
||
|
* @return bool
|
||
|
*/
|
||
|
public function deleteByUser(string $user): bool {
|
||
|
$notification = $this->manager->createNotification();
|
||
|
try {
|
||
|
$notification->setUser($user);
|
||
|
} catch (\InvalidArgumentException $e) {
|
||
|
return false;
|
||
|
}
|
||
|
return !empty($this->delete($notification));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Delete the notification matching the given id
|
||
|
*
|
||
|
* @param int $id
|
||
|
* @param string $user
|
||
|
* @return bool
|
||
|
*/
|
||
|
public function deleteById(int $id, string $user): bool {
|
||
|
$sql = $this->connection->getQueryBuilder();
|
||
|
$sql->delete('notifications')
|
||
|
->where($sql->expr()->eq('notification_id', $sql->createNamedParameter($id)))
|
||
|
->andWhere($sql->expr()->eq('user', $sql->createNamedParameter($user)));
|
||
|
return (bool) $sql->execute();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the notification matching the given id
|
||
|
*
|
||
|
* @param int $id
|
||
|
* @param string $user
|
||
|
* @return INotification
|
||
|
* @throws NotificationNotFoundException
|
||
|
*/
|
||
|
public function getById(int $id, string $user): INotification {
|
||
|
$sql = $this->connection->getQueryBuilder();
|
||
|
$sql->select('*')
|
||
|
->from('notifications')
|
||
|
->where($sql->expr()->eq('notification_id', $sql->createNamedParameter($id)))
|
||
|
->andWhere($sql->expr()->eq('user', $sql->createNamedParameter($user)));
|
||
|
$statement = $sql->execute();
|
||
|
$row = $statement->fetch();
|
||
|
$statement->closeCursor();
|
||
|
|
||
|
if ($row === false) {
|
||
|
throw new NotificationNotFoundException('No entry returned from database');
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
return $this->notificationFromRow($row);
|
||
|
} catch (\InvalidArgumentException $e) {
|
||
|
throw new NotificationNotFoundException('Could not create notification from database row');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return the notifications matching the given Notification
|
||
|
*
|
||
|
* @param INotification $notification
|
||
|
* @param int $limit
|
||
|
* @return array [notification_id => INotification]
|
||
|
*/
|
||
|
public function get(INotification $notification, $limit = 25): array {
|
||
|
$sql = $this->connection->getQueryBuilder();
|
||
|
$sql->select('*')
|
||
|
->from('notifications')
|
||
|
->orderBy('notification_id', 'DESC')
|
||
|
->setMaxResults($limit);
|
||
|
|
||
|
$this->sqlWhere($sql, $notification);
|
||
|
$statement = $sql->execute();
|
||
|
|
||
|
$notifications = [];
|
||
|
while ($row = $statement->fetch()) {
|
||
|
try {
|
||
|
$notifications[(int)$row['notification_id']] = $this->notificationFromRow($row);
|
||
|
} catch (\InvalidArgumentException $e) {
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
$statement->closeCursor();
|
||
|
|
||
|
return $notifications;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Add where statements to a query builder matching the given notification
|
||
|
*
|
||
|
* @param IQueryBuilder $sql
|
||
|
* @param INotification $notification
|
||
|
*/
|
||
|
protected function sqlWhere(IQueryBuilder $sql, INotification $notification) {
|
||
|
if ($notification->getApp() !== '') {
|
||
|
$sql->andWhere($sql->expr()->eq('app', $sql->createNamedParameter($notification->getApp())));
|
||
|
}
|
||
|
|
||
|
if ($notification->getUser() !== '') {
|
||
|
$sql->andWhere($sql->expr()->eq('user', $sql->createNamedParameter($notification->getUser())));
|
||
|
}
|
||
|
|
||
|
$timestamp = $notification->getDateTime()->getTimestamp();
|
||
|
if ($timestamp !== 0) {
|
||
|
$sql->andWhere($sql->expr()->eq('timestamp', $sql->createNamedParameter($timestamp)));
|
||
|
}
|
||
|
|
||
|
if ($notification->getObjectType() !== '') {
|
||
|
$sql->andWhere($sql->expr()->eq('object_type', $sql->createNamedParameter($notification->getObjectType())));
|
||
|
}
|
||
|
|
||
|
if ($notification->getObjectId() !== '') {
|
||
|
$sql->andWhere($sql->expr()->eq('object_id', $sql->createNamedParameter($notification->getObjectId())));
|
||
|
}
|
||
|
|
||
|
if ($notification->getSubject() !== '') {
|
||
|
$sql->andWhere($sql->expr()->eq('subject', $sql->createNamedParameter($notification->getSubject())));
|
||
|
}
|
||
|
|
||
|
if ($notification->getMessage() !== '') {
|
||
|
$sql->andWhere($sql->expr()->eq('message', $sql->createNamedParameter($notification->getMessage())));
|
||
|
}
|
||
|
|
||
|
if ($notification->getLink() !== '') {
|
||
|
$sql->andWhere($sql->expr()->eq('link', $sql->createNamedParameter($notification->getLink())));
|
||
|
}
|
||
|
|
||
|
if ($notification->getIcon() !== '') {
|
||
|
$sql->andWhere($sql->expr()->eq('icon', $sql->createNamedParameter($notification->getIcon())));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Turn a notification into an input statement
|
||
|
*
|
||
|
* @param IQueryBuilder $sql
|
||
|
* @param INotification $notification
|
||
|
*/
|
||
|
protected function sqlInsert(IQueryBuilder $sql, INotification $notification) {
|
||
|
$actions = [];
|
||
|
foreach ($notification->getActions() as $action) {
|
||
|
/** @var IAction $action */
|
||
|
$actions[] = [
|
||
|
'label' => $action->getLabel(),
|
||
|
'link' => $action->getLink(),
|
||
|
'type' => $action->getRequestType(),
|
||
|
'primary' => $action->isPrimary(),
|
||
|
];
|
||
|
}
|
||
|
|
||
|
$sql->setValue('app', $sql->createNamedParameter($notification->getApp()))
|
||
|
->setValue('user', $sql->createNamedParameter($notification->getUser()))
|
||
|
->setValue('timestamp', $sql->createNamedParameter($notification->getDateTime()->getTimestamp()))
|
||
|
->setValue('object_type', $sql->createNamedParameter($notification->getObjectType()))
|
||
|
->setValue('object_id', $sql->createNamedParameter($notification->getObjectId()))
|
||
|
->setValue('subject', $sql->createNamedParameter($notification->getSubject()))
|
||
|
->setValue('subject_parameters', $sql->createNamedParameter(json_encode($notification->getSubjectParameters())))
|
||
|
->setValue('message', $sql->createNamedParameter($notification->getMessage()))
|
||
|
->setValue('message_parameters', $sql->createNamedParameter(json_encode($notification->getMessageParameters())))
|
||
|
->setValue('link', $sql->createNamedParameter($notification->getLink()))
|
||
|
->setValue('icon', $sql->createNamedParameter($notification->getIcon()))
|
||
|
->setValue('actions', $sql->createNamedParameter(json_encode($actions)));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Turn a database row into a INotification
|
||
|
*
|
||
|
* @param array $row
|
||
|
* @return INotification
|
||
|
* @throws \InvalidArgumentException
|
||
|
*/
|
||
|
protected function notificationFromRow(array $row): INotification {
|
||
|
$dateTime = new \DateTime();
|
||
|
$dateTime->setTimestamp((int) $row['timestamp']);
|
||
|
|
||
|
$notification = $this->manager->createNotification();
|
||
|
$notification->setApp($row['app'])
|
||
|
->setUser($row['user'])
|
||
|
->setDateTime($dateTime)
|
||
|
->setObject($row['object_type'], $row['object_id'])
|
||
|
->setSubject($row['subject'], (array) json_decode($row['subject_parameters'], true));
|
||
|
|
||
|
if ($row['message'] !== '') {
|
||
|
$notification->setMessage($row['message'], (array) json_decode($row['message_parameters'], true));
|
||
|
}
|
||
|
if ($row['link'] !== '' && $row['link'] !== null) {
|
||
|
$notification->setLink($row['link']);
|
||
|
}
|
||
|
if ($row['icon'] !== '' && $row['icon'] !== null) {
|
||
|
$notification->setIcon($row['icon']);
|
||
|
}
|
||
|
|
||
|
$actions = (array) json_decode($row['actions'], true);
|
||
|
foreach ($actions as $actionData) {
|
||
|
$action = $notification->createAction();
|
||
|
$action->setLabel($actionData['label'])
|
||
|
->setLink($actionData['link'], $actionData['type']);
|
||
|
if (isset($actionData['primary'])) {
|
||
|
$action->setPrimary($actionData['primary']);
|
||
|
}
|
||
|
$notification->addAction($action);
|
||
|
}
|
||
|
|
||
|
return $notification;
|
||
|
}
|
||
|
}
|