Signed-off-by: Christopher Ng <chrng8@gmail.com>pull/39651/head
parent
a3ac1b82da
commit
ea5e128fef
@ -0,0 +1,32 @@ |
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
/** |
||||
* @copyright 2023 Christopher Ng <chrng8@gmail.com> |
||||
* |
||||
* @author Christopher Ng <chrng8@gmail.com> |
||||
* |
||||
* @license GNU AGPL version 3 or any later version |
||||
* |
||||
* This program is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License as |
||||
* published by the Free Software Foundation, either version 3 of the |
||||
* License, or (at your option) any later version. |
||||
* |
||||
* 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 |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
namespace OCA\FilesReminders\Exception; |
||||
|
||||
use Exception; |
||||
|
||||
class NodeNotFoundException extends Exception { |
||||
} |
||||
@ -0,0 +1,32 @@ |
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
/** |
||||
* @copyright 2023 Christopher Ng <chrng8@gmail.com> |
||||
* |
||||
* @author Christopher Ng <chrng8@gmail.com> |
||||
* |
||||
* @license GNU AGPL version 3 or any later version |
||||
* |
||||
* This program is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License as |
||||
* published by the Free Software Foundation, either version 3 of the |
||||
* License, or (at your option) any later version. |
||||
* |
||||
* 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 |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
namespace OCA\FilesReminders\Exception; |
||||
|
||||
use Exception; |
||||
|
||||
class UserNotFoundException extends Exception { |
||||
} |
||||
@ -0,0 +1,142 @@ |
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
/** |
||||
* @copyright 2023 Christopher Ng <chrng8@gmail.com> |
||||
* |
||||
* @author Christopher Ng <chrng8@gmail.com> |
||||
* |
||||
* @license GNU AGPL version 3 or any later version |
||||
* |
||||
* This program is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License as |
||||
* published by the Free Software Foundation, either version 3 of the |
||||
* License, or (at your option) any later version. |
||||
* |
||||
* 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 |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
namespace OCA\FilesReminders\Notification; |
||||
|
||||
use InvalidArgumentException; |
||||
use OCA\FilesReminders\AppInfo\Application; |
||||
use OCA\FilesReminders\Exception\NodeNotFoundException; |
||||
use OCP\Files\FileInfo; |
||||
use OCP\Files\IRootFolder; |
||||
use OCP\Files\Node; |
||||
use OCP\IURLGenerator; |
||||
use OCP\L10N\IFactory; |
||||
use OCP\Notification\IAction; |
||||
use OCP\Notification\INotification; |
||||
use OCP\Notification\INotifier; |
||||
|
||||
class Notifier implements INotifier { |
||||
public function __construct( |
||||
protected IFactory $l10nFactory, |
||||
protected IURLGenerator $urlGenerator, |
||||
protected IRootFolder $root, |
||||
) {} |
||||
|
||||
public function getID(): string { |
||||
return Application::APP_ID; |
||||
} |
||||
|
||||
public function getName(): string { |
||||
return $this->l10nFactory->get(Application::APP_ID)->t('File reminders'); |
||||
} |
||||
|
||||
/** |
||||
* @throws InvalidArgumentException |
||||
* @throws NodeNotFoundException |
||||
*/ |
||||
public function prepare(INotification $notification, string $languageCode): INotification { |
||||
$l = $this->l10nFactory->get(Application::APP_ID, $languageCode); |
||||
|
||||
if ($notification->getApp() !== Application::APP_ID) { |
||||
throw new InvalidArgumentException(); |
||||
} |
||||
|
||||
switch ($notification->getSubject()) { |
||||
case 'reminder-due': |
||||
$fileId = $notification->getSubjectParameters()['fileId']; |
||||
$node = $this->getNode($fileId); |
||||
|
||||
$path = rtrim($node->getPath(), '/'); |
||||
if (strpos($path, '/' . $notification->getUser() . '/files/') === 0) { |
||||
// Remove /user/files/... |
||||
$fullPath = $path; |
||||
[,,, $path] = explode('/', $fullPath, 4); |
||||
} |
||||
|
||||
$link = $this->urlGenerator->linkToRouteAbsolute( |
||||
'files.viewcontroller.showFile', |
||||
['fileid' => $node->getId()], |
||||
); |
||||
|
||||
$subject = $l->t('Reminder for {filename}'); |
||||
$notification |
||||
->setRichSubject( |
||||
$subject, |
||||
[ |
||||
'filename' => [ |
||||
'type' => 'file', |
||||
'id' => $node->getId(), |
||||
'name' => $node->getName(), |
||||
'path' => $path, |
||||
'link' => $link, |
||||
], |
||||
], |
||||
) |
||||
->setParsedSubject(str_replace( |
||||
['{filename}'], |
||||
[$node->getName()], |
||||
$subject, |
||||
)) |
||||
->setLink($link); |
||||
|
||||
$label = match ($node->getType()) { |
||||
FileInfo::TYPE_FILE => $l->t('View file'), |
||||
FileInfo::TYPE_FOLDER => $l->t('View folder'), |
||||
}; |
||||
|
||||
$this->addActionButton($notification, $label); |
||||
break; |
||||
default: |
||||
throw new InvalidArgumentException(); |
||||
break; |
||||
} |
||||
|
||||
return $notification; |
||||
} |
||||
|
||||
protected function addActionButton(INotification $notification, string $label): void { |
||||
$action = $notification->createAction(); |
||||
|
||||
$action->setLabel($label) |
||||
->setParsedLabel($label) |
||||
->setLink($notification->getLink(), IAction::TYPE_WEB) |
||||
->setPrimary(true); |
||||
|
||||
$notification->addParsedAction($action); |
||||
} |
||||
|
||||
/** |
||||
* @throws NodeNotFoundException |
||||
*/ |
||||
protected function getNode(int $fileId): Node { |
||||
$nodes = $this->root->getById($fileId); |
||||
if (empty($nodes)) { |
||||
throw new NodeNotFoundException(); |
||||
} |
||||
$node = reset($nodes); |
||||
return $node; |
||||
} |
||||
} |
||||
@ -0,0 +1,87 @@ |
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
/** |
||||
* @copyright 2023 Christopher Ng <chrng8@gmail.com> |
||||
* |
||||
* @author Christopher Ng <chrng8@gmail.com> |
||||
* |
||||
* @license GNU AGPL version 3 or any later version |
||||
* |
||||
* This program is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License as |
||||
* published by the Free Software Foundation, either version 3 of the |
||||
* License, or (at your option) any later version. |
||||
* |
||||
* 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 |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
namespace OCA\FilesReminders\Service; |
||||
|
||||
use DateTime; |
||||
use InvalidArgumentException; |
||||
use OCA\FilesReminders\AppInfo\Application; |
||||
use OCA\FilesReminders\Db\Reminder; |
||||
use OCA\FilesReminders\Db\ReminderMapper; |
||||
use OCA\FilesReminders\Exception\UserNotFoundException; |
||||
use OCP\AppFramework\Db\DoesNotExistException; |
||||
use OCP\IURLGenerator; |
||||
use OCP\IUserManager; |
||||
use OCP\Notification\IManager as INotificationManager; |
||||
use Psr\Log\LoggerInterface; |
||||
|
||||
class ReminderService { |
||||
public function __construct( |
||||
protected IUserManager $userManager, |
||||
protected IURLGenerator $urlGenerator, |
||||
protected INotificationManager $notificationManager, |
||||
protected ReminderMapper $reminderMapper, |
||||
protected LoggerInterface $logger, |
||||
) {} |
||||
|
||||
/** |
||||
* @throws DoesNotExistException |
||||
* @throws UserNotFoundException |
||||
*/ |
||||
public function send(Reminder $reminder): void { |
||||
if ($reminder->getNotified()) { |
||||
return; |
||||
} |
||||
|
||||
$user = $this->userManager->get($reminder->getUserId()); |
||||
if ($user === null) { |
||||
throw new UserNotFoundException(); |
||||
} |
||||
|
||||
$notification = $this->notificationManager->createNotification(); |
||||
$notification |
||||
->setApp(Application::APP_ID) |
||||
->setIcon($this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('files', 'folder.svg'))) |
||||
->setUser($user->getUID()) |
||||
->setObject('reminder', (string)$reminder->getId()) |
||||
->setSubject('reminder-due', ['fileId' => $reminder->getFileId()]) |
||||
->setDateTime(DateTime::createFromFormat('U', (string)$reminder->getRemindAt())); |
||||
|
||||
try { |
||||
$this->notificationManager->notify($notification); |
||||
$this->reminderMapper->markNotified($reminder); |
||||
} catch (InvalidArgumentException $e) { |
||||
$this->logger->error('Failed to send reminder notification', $e->getTrace()); |
||||
} |
||||
} |
||||
|
||||
public function cleanUp(?int $limit = null): void { |
||||
$reminders = $this->reminderMapper->findToDelete($limit); |
||||
foreach ($reminders as $reminder) { |
||||
$this->reminderMapper->delete($reminder); |
||||
} |
||||
} |
||||
} |
||||
Loading…
Reference in new issue