]> source.dussan.org Git - nextcloud-server.git/commitdiff
feat(files_reminders): add list command
authorChristopher Ng <chrng8@gmail.com>
Mon, 31 Jul 2023 19:10:50 +0000 (12:10 -0700)
committerChristopher Ng <chrng8@gmail.com>
Thu, 3 Aug 2023 22:30:11 +0000 (15:30 -0700)
Signed-off-by: Christopher Ng <chrng8@gmail.com>
apps/files_reminders/lib/Command/ListCommand.php [new file with mode: 0644]
apps/files_reminders/lib/Db/Reminder.php
apps/files_reminders/lib/Db/ReminderMapper.php
apps/files_reminders/lib/Model/RichReminder.php [new file with mode: 0644]
apps/files_reminders/lib/Notification/Notifier.php
apps/files_reminders/lib/Service/ReminderService.php

diff --git a/apps/files_reminders/lib/Command/ListCommand.php b/apps/files_reminders/lib/Command/ListCommand.php
new file mode 100644 (file)
index 0000000..35a778e
--- /dev/null
@@ -0,0 +1,92 @@
+<?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\Command;
+
+use DateTime;
+use DateTimeInterface;
+use OC\Core\Command\Base;
+use OCA\FilesReminders\Model\RichReminder;
+use OCA\FilesReminders\Service\ReminderService;
+use OCP\IUserManager;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
+
+class ListCommand extends Base {
+       public function __construct(
+               private ReminderService $reminderService,
+               private IUserManager $userManager,
+       ) {
+               parent::__construct();
+       }
+
+       protected function configure(): void {
+               $this
+                       ->setName('files:reminders')
+                       ->setDescription('List file reminders')
+                       ->addArgument(
+                               'user',
+                               InputArgument::OPTIONAL,
+                               'list reminders for user',
+                       );
+       }
+
+       protected function execute(InputInterface $input, OutputInterface $output): int {
+               $io = new SymfonyStyle($input, $output);
+
+               $uid = $input->getArgument('user');
+               if ($uid !== null) {
+                       /** @var string $uid */
+                       $user = $this->userManager->get($uid);
+                       if ($user === null) {
+                               $io->error("Unknown user <$uid>");
+                               return 1;
+                       }
+               }
+
+               $reminders = $this->reminderService->getAll($user ?? null);
+               if (empty($reminders)) {
+                       $io->text('No reminders');
+                       return 0;
+               }
+
+               $io->table(
+                       ['UserId', 'Path', 'RemindAt', 'Notified'],
+                       array_map(
+                               fn (RichReminder $reminder) => [
+                                       $reminder->getUserId(),
+                                       $reminder->getNode()->getPath(),
+                                       DateTime::createFromFormat('U', (string)$reminder->getRemindAt())->format(DateTimeInterface::ATOM), // ISO 8601
+                                       $reminder->getNotified() ? 'true' : 'false',
+                               ],
+                               $reminders,
+                       )
+               );
+               return 0;
+       }
+}
index 98e2cc5838f632b426ce405b2d0e9b8bd51854a9..99cd9b590922cc8631b0911c0386184aaec8faa8 100644 (file)
@@ -42,10 +42,10 @@ use OCP\AppFramework\Db\Entity;
  * @method bool getNotified()
  */
 class Reminder extends Entity {
-       protected string $userId;
-       protected int $fileId;
-       protected int $remindAt;
-       protected bool $notified = false;
+       protected $userId;
+       protected $fileId;
+       protected $remindAt;
+       protected $notified = false;
 
        public function __construct() {
                $this->addType('userId', 'string');
index f383ee66511b2525624884f96255248e13e282db..6b2e3a1f2b87cb3f6da56cf615990a7a79eddb94 100644 (file)
@@ -29,6 +29,7 @@ namespace OCA\FilesReminders\Db;
 use OCP\AppFramework\Db\QBMapper;
 use OCP\DB\QueryBuilder\IQueryBuilder;
 use OCP\IDBConnection;
+use OCP\IUser;
 
 /**
  * @template-extends QBMapper<Reminder>
@@ -51,13 +52,50 @@ class ReminderMapper extends QBMapper {
                return parent::update($reminderUpdate);
        }
 
+       public function find(int $id): Reminder {
+               $qb = $this->db->getQueryBuilder();
+
+               $qb->select('user_id', 'file_id', 'remind_at', 'notified')
+               ->from($this->getTableName())
+                       ->where($qb->expr()->eq('id', $qb->createNamedParameter($id, IQueryBuilder::PARAM_INT)));
+
+               return $this->findEntity($qb);
+       }
+
+       /**
+        * @return Reminder[]
+        */
+       public function findAll() {
+               $qb = $this->db->getQueryBuilder();
+
+               $qb->select('user_id', 'file_id', 'remind_at', 'notified')
+                       ->from($this->getTableName())
+                       ->orderBy('remind_at', 'ASC');
+
+               return $this->findEntities($qb);
+       }
+
+       /**
+        * @return Reminder[]
+        */
+       public function findAllForUser(IUser $user) {
+               $qb = $this->db->getQueryBuilder();
+
+               $qb->select('user_id', 'file_id', 'remind_at', 'notified')
+               ->from($this->getTableName())
+                       ->where($qb->expr()->eq('user_id', $qb->createNamedParameter($user->getUID(), IQueryBuilder::PARAM_STR)))
+                       ->orderBy('remind_at', 'ASC');
+
+               return $this->findEntities($qb);
+       }
+
        /**
         * @return Reminder[]
         */
        public function findToRemind() {
                $qb = $this->db->getQueryBuilder();
 
-               $qb->select('user_id', 'file_id', 'remind_at')
+               $qb->select('user_id', 'file_id', 'remind_at', 'notified')
                        ->from($this->getTableName())
                        ->where($qb->expr()->lt('remind_at', $qb->createFunction('NOW()')))
                        ->andWhere($qb->expr()->eq('notified', $qb->createNamedParameter(false, IQueryBuilder::PARAM_BOOL)))
@@ -72,7 +110,7 @@ class ReminderMapper extends QBMapper {
        public function findToDelete(?int $limit = null) {
                $qb = $this->db->getQueryBuilder();
 
-               $qb->select('user_id', 'file_id', 'remind_at')
+               $qb->select('user_id', 'file_id', 'remind_at', 'notified')
                        ->from($this->getTableName())
                        ->where($qb->expr()->eq('notified', $qb->createNamedParameter(true, IQueryBuilder::PARAM_BOOL)))
                        ->orderBy('remind_at', 'ASC')
diff --git a/apps/files_reminders/lib/Model/RichReminder.php b/apps/files_reminders/lib/Model/RichReminder.php
new file mode 100644 (file)
index 0000000..21b42d9
--- /dev/null
@@ -0,0 +1,62 @@
+<?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\Model;
+
+use OCA\FilesReminders\Db\Reminder;
+use OCA\FilesReminders\Exception\NodeNotFoundException;
+use OCP\Files\IRootFolder;
+use OCP\Files\Node;
+
+class RichReminder extends Reminder {
+       public function __construct(
+               private Reminder $reminder,
+               private IRootFolder $root,
+       ) {
+               parent::__construct();
+       }
+
+       /**
+        * @throws NodeNotFoundException
+        */
+       public function getNode(): Node {
+               $userFolder = $this->root->getUserFolder($this->getUserId());
+               $nodes = $userFolder->getById($this->getFileId());
+               if (empty($nodes)) {
+                       throw new NodeNotFoundException();
+               }
+               $node = reset($nodes);
+               return $node;
+       }
+
+       protected function getter(string $name): mixed {
+               return $this->reminder->getter($name);
+       }
+
+       public function __call(string $methodName, array $args) {
+               return $this->reminder->__call($methodName, $args);
+       }
+}
index b3c1a98484a15d2a15121d0fc04529f9afe75937..fb1d3264dbda682aa73105324a5c700ba0925744 100644 (file)
@@ -29,9 +29,8 @@ namespace OCA\FilesReminders\Notification;
 use InvalidArgumentException;
 use OCA\FilesReminders\AppInfo\Application;
 use OCA\FilesReminders\Exception\NodeNotFoundException;
+use OCA\FilesReminders\Service\ReminderService;
 use OCP\Files\FileInfo;
-use OCP\Files\IRootFolder;
-use OCP\Files\Node;
 use OCP\IURLGenerator;
 use OCP\L10N\IFactory;
 use OCP\Notification\IAction;
@@ -42,7 +41,7 @@ class Notifier implements INotifier {
        public function __construct(
                protected IFactory $l10nFactory,
                protected IURLGenerator $urlGenerator,
-               protected IRootFolder $root,
+               protected ReminderService $reminderService,
        ) {}
 
        public function getID(): string {
@@ -66,8 +65,8 @@ class Notifier implements INotifier {
 
                switch ($notification->getSubject()) {
                        case 'reminder-due':
-                               $fileId = $notification->getSubjectParameters()['fileId'];
-                               $node = $this->getNode($fileId);
+                               $reminderId = (int)$notification->getObjectId();
+                               $node = $this->reminderService->get($reminderId)->getNode();
 
                                $path = rtrim($node->getPath(), '/');
                                if (strpos($path, '/' . $notification->getUser() . '/files/') === 0) {
@@ -81,12 +80,13 @@ class Notifier implements INotifier {
                                        ['fileid' => $node->getId()],
                                );
 
-                               $subject = $l->t('Reminder for {filename}');
+                               // TRANSLATORS The name placeholder is for a file or folder name
+                               $subject = $l->t('Reminder for {name}');
                                $notification
                                        ->setRichSubject(
                                                $subject,
                                                [
-                                                       'filename' => [
+                                                       'name' => [
                                                                'type' => 'file',
                                                                'id' => $node->getId(),
                                                                'name' => $node->getName(),
@@ -96,7 +96,7 @@ class Notifier implements INotifier {
                                                ],
                                        )
                                        ->setParsedSubject(str_replace(
-                                               ['{filename}'],
+                                               ['{name}'],
                                                [$node->getName()],
                                                $subject,
                                        ))
@@ -127,16 +127,4 @@ class Notifier implements INotifier {
 
                $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;
-       }
 }
index 69cef36785634739bf6b61da763949df7778df4b..e65cdbfb86723c8498c30f52527d123aa18051e4 100644 (file)
@@ -32,8 +32,11 @@ use OCA\FilesReminders\AppInfo\Application;
 use OCA\FilesReminders\Db\Reminder;
 use OCA\FilesReminders\Db\ReminderMapper;
 use OCA\FilesReminders\Exception\UserNotFoundException;
+use OCA\FilesReminders\Model\RichReminder;
 use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\Files\IRootFolder;
 use OCP\IURLGenerator;
+use OCP\IUser;
 use OCP\IUserManager;
 use OCP\Notification\IManager as INotificationManager;
 use Psr\Log\LoggerInterface;
@@ -44,9 +47,28 @@ class ReminderService {
                protected IURLGenerator $urlGenerator,
                protected INotificationManager $notificationManager,
                protected ReminderMapper $reminderMapper,
+               protected IRootFolder $root,
                protected LoggerInterface $logger,
        ) {}
 
+       public function get(int $id): RichReminder {
+               $reminder = $this->reminderMapper->find($id);
+               return new RichReminder($reminder, $this->root);
+       }
+
+       /**
+        * @return RichReminder[]
+        */
+       public function getAll(?IUser $user = null) {
+               $reminders = ($user !== null)
+                       ? $this->reminderMapper->findAllForUser($user)
+                       : $this->reminderMapper->findAll();
+               return array_map(
+                       fn (Reminder $reminder) => new RichReminder($reminder, $this->root),
+                       $reminders,
+               );
+       }
+
        /**
         * @throws DoesNotExistException
         * @throws UserNotFoundException
@@ -67,7 +89,7 @@ class ReminderService {
                        ->setIcon($this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('files', 'folder.svg')))
                        ->setUser($user->getUID())
                        ->setObject('reminder', (string)$reminder->getId())
-                       ->setSubject('reminder-due', ['fileId' => $reminder->getFileId()])
+                       ->setSubject('reminder-due')
                        ->setDateTime(DateTime::createFromFormat('U', (string)$reminder->getRemindAt()));
 
                try {