Skip to content

Commit c8a32a7

Browse files
committed
feat(files_reminders): add list command
Signed-off-by: Christopher Ng <[email protected]>
1 parent ea5e128 commit c8a32a7

File tree

6 files changed

+229
-27
lines changed

6 files changed

+229
-27
lines changed
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* @copyright 2023 Christopher Ng <[email protected]>
7+
*
8+
* @author Christopher Ng <[email protected]>
9+
*
10+
* @license GNU AGPL version 3 or any later version
11+
*
12+
* This program is free software: you can redistribute it and/or modify
13+
* it under the terms of the GNU Affero General Public License as
14+
* published by the Free Software Foundation, either version 3 of the
15+
* License, or (at your option) any later version.
16+
*
17+
* This program is distributed in the hope that it will be useful,
18+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
19+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+
* GNU Affero General Public License for more details.
21+
*
22+
* You should have received a copy of the GNU Affero General Public License
23+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
24+
*
25+
*/
26+
27+
namespace OCA\FilesReminders\Command;
28+
29+
use DateTime;
30+
use DateTimeInterface;
31+
use OC\Core\Command\Base;
32+
use OCA\FilesReminders\Model\RichReminder;
33+
use OCA\FilesReminders\Service\ReminderService;
34+
use OCP\IUserManager;
35+
use Symfony\Component\Console\Input\InputArgument;
36+
use Symfony\Component\Console\Input\InputInterface;
37+
use Symfony\Component\Console\Output\OutputInterface;
38+
use Symfony\Component\Console\Style\SymfonyStyle;
39+
40+
class ListCommand extends Base {
41+
public function __construct(
42+
private ReminderService $reminderService,
43+
private IUserManager $userManager,
44+
) {
45+
parent::__construct();
46+
}
47+
48+
protected function configure(): void {
49+
$this
50+
->setName('files:reminders')
51+
->setDescription('List file reminders')
52+
->addArgument(
53+
'user',
54+
InputArgument::OPTIONAL,
55+
'list reminders for user',
56+
);
57+
}
58+
59+
protected function execute(InputInterface $input, OutputInterface $output): int {
60+
$io = new SymfonyStyle($input, $output);
61+
62+
$uid = $input->getArgument('user');
63+
if ($uid !== null) {
64+
/** @var string $uid */
65+
$user = $this->userManager->get($uid);
66+
if ($user === null) {
67+
$io->error("Unknown user <$uid>");
68+
return 1;
69+
}
70+
}
71+
72+
$reminders = $this->reminderService->getAll($user ?? null);
73+
if (empty($reminders)) {
74+
$io->text('No reminders');
75+
return 0;
76+
}
77+
78+
$io->table(
79+
['UserId', 'Path', 'RemindAt', 'Notified'],
80+
array_map(
81+
fn (RichReminder $reminder) => [
82+
$reminder->getUserId(),
83+
$reminder->getNode()->getPath(),
84+
DateTime::createFromFormat('U', (string)$reminder->getRemindAt())->format(DateTimeInterface::ATOM), // ISO 8601
85+
$reminder->getNotified() ? 'true' : 'false',
86+
],
87+
$reminders,
88+
)
89+
);
90+
return 0;
91+
}
92+
}

apps/files_reminders/lib/Db/Reminder.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,10 @@
4242
* @method bool getNotified()
4343
*/
4444
class Reminder extends Entity {
45-
protected string $userId;
46-
protected int $fileId;
47-
protected int $remindAt;
48-
protected bool $notified = false;
45+
protected $userId;
46+
protected $fileId;
47+
protected $remindAt;
48+
protected $notified = false;
4949

5050
public function __construct() {
5151
$this->addType('userId', 'string');

apps/files_reminders/lib/Db/ReminderMapper.php

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
use OCP\AppFramework\Db\QBMapper;
3030
use OCP\DB\QueryBuilder\IQueryBuilder;
3131
use OCP\IDBConnection;
32+
use OCP\IUser;
3233

3334
/**
3435
* @template-extends QBMapper<Reminder>
@@ -51,13 +52,50 @@ public function markNotified(Reminder $reminder): Reminder {
5152
return parent::update($reminderUpdate);
5253
}
5354

55+
public function find(int $id): Reminder {
56+
$qb = $this->db->getQueryBuilder();
57+
58+
$qb->select('user_id', 'file_id', 'remind_at', 'notified')
59+
->from($this->getTableName())
60+
->where($qb->expr()->eq('id', $qb->createNamedParameter($id, IQueryBuilder::PARAM_INT)));
61+
62+
return $this->findEntity($qb);
63+
}
64+
65+
/**
66+
* @return Reminder[]
67+
*/
68+
public function findAll() {
69+
$qb = $this->db->getQueryBuilder();
70+
71+
$qb->select('user_id', 'file_id', 'remind_at', 'notified')
72+
->from($this->getTableName())
73+
->orderBy('remind_at', 'ASC');
74+
75+
return $this->findEntities($qb);
76+
}
77+
78+
/**
79+
* @return Reminder[]
80+
*/
81+
public function findAllForUser(IUser $user) {
82+
$qb = $this->db->getQueryBuilder();
83+
84+
$qb->select('user_id', 'file_id', 'remind_at', 'notified')
85+
->from($this->getTableName())
86+
->where($qb->expr()->eq('user_id', $qb->createNamedParameter($user->getUID(), IQueryBuilder::PARAM_STR)))
87+
->orderBy('remind_at', 'ASC');
88+
89+
return $this->findEntities($qb);
90+
}
91+
5492
/**
5593
* @return Reminder[]
5694
*/
5795
public function findToRemind() {
5896
$qb = $this->db->getQueryBuilder();
5997

60-
$qb->select('user_id', 'file_id', 'remind_at')
98+
$qb->select('user_id', 'file_id', 'remind_at', 'notified')
6199
->from($this->getTableName())
62100
->where($qb->expr()->lt('remind_at', $qb->createFunction('NOW()')))
63101
->andWhere($qb->expr()->eq('notified', $qb->createNamedParameter(false, IQueryBuilder::PARAM_BOOL)))
@@ -72,7 +110,7 @@ public function findToRemind() {
72110
public function findToDelete(?int $limit = null) {
73111
$qb = $this->db->getQueryBuilder();
74112

75-
$qb->select('user_id', 'file_id', 'remind_at')
113+
$qb->select('user_id', 'file_id', 'remind_at', 'notified')
76114
->from($this->getTableName())
77115
->where($qb->expr()->eq('notified', $qb->createNamedParameter(true, IQueryBuilder::PARAM_BOOL)))
78116
->orderBy('remind_at', 'ASC')
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* @copyright 2023 Christopher Ng <[email protected]>
7+
*
8+
* @author Christopher Ng <[email protected]>
9+
*
10+
* @license GNU AGPL version 3 or any later version
11+
*
12+
* This program is free software: you can redistribute it and/or modify
13+
* it under the terms of the GNU Affero General Public License as
14+
* published by the Free Software Foundation, either version 3 of the
15+
* License, or (at your option) any later version.
16+
*
17+
* This program is distributed in the hope that it will be useful,
18+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
19+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+
* GNU Affero General Public License for more details.
21+
*
22+
* You should have received a copy of the GNU Affero General Public License
23+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
24+
*
25+
*/
26+
27+
namespace OCA\FilesReminders\Model;
28+
29+
use OCA\FilesReminders\Db\Reminder;
30+
use OCA\FilesReminders\Exception\NodeNotFoundException;
31+
use OCP\Files\IRootFolder;
32+
use OCP\Files\Node;
33+
34+
class RichReminder extends Reminder {
35+
public function __construct(
36+
private Reminder $reminder,
37+
private IRootFolder $root,
38+
) {
39+
parent::__construct();
40+
}
41+
42+
/**
43+
* @throws NodeNotFoundException
44+
*/
45+
public function getNode(): Node {
46+
$userFolder = $this->root->getUserFolder($this->getUserId());
47+
$nodes = $userFolder->getById($this->getFileId());
48+
if (empty($nodes)) {
49+
throw new NodeNotFoundException();
50+
}
51+
$node = reset($nodes);
52+
return $node;
53+
}
54+
55+
protected function getter(string $name): mixed {
56+
return $this->reminder->getter($name);
57+
}
58+
59+
public function __call(string $methodName, array $args) {
60+
return $this->reminder->__call($methodName, $args);
61+
}
62+
}

apps/files_reminders/lib/Notification/Notifier.php

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,8 @@
2929
use InvalidArgumentException;
3030
use OCA\FilesReminders\AppInfo\Application;
3131
use OCA\FilesReminders\Exception\NodeNotFoundException;
32+
use OCA\FilesReminders\Service\ReminderService;
3233
use OCP\Files\FileInfo;
33-
use OCP\Files\IRootFolder;
34-
use OCP\Files\Node;
3534
use OCP\IURLGenerator;
3635
use OCP\L10N\IFactory;
3736
use OCP\Notification\IAction;
@@ -42,7 +41,7 @@ class Notifier implements INotifier {
4241
public function __construct(
4342
protected IFactory $l10nFactory,
4443
protected IURLGenerator $urlGenerator,
45-
protected IRootFolder $root,
44+
protected ReminderService $reminderService,
4645
) {}
4746

4847
public function getID(): string {
@@ -66,8 +65,8 @@ public function prepare(INotification $notification, string $languageCode): INot
6665

6766
switch ($notification->getSubject()) {
6867
case 'reminder-due':
69-
$fileId = $notification->getSubjectParameters()['fileId'];
70-
$node = $this->getNode($fileId);
68+
$reminderId = (int)$notification->getObjectId();
69+
$node = $this->reminderService->get($reminderId)->getNode();
7170

7271
$path = rtrim($node->getPath(), '/');
7372
if (strpos($path, '/' . $notification->getUser() . '/files/') === 0) {
@@ -81,12 +80,13 @@ public function prepare(INotification $notification, string $languageCode): INot
8180
['fileid' => $node->getId()],
8281
);
8382

84-
$subject = $l->t('Reminder for {filename}');
83+
// TRANSLATORS The name placeholder is for a file or folder name
84+
$subject = $l->t('Reminder for {name}');
8585
$notification
8686
->setRichSubject(
8787
$subject,
8888
[
89-
'filename' => [
89+
'name' => [
9090
'type' => 'file',
9191
'id' => $node->getId(),
9292
'name' => $node->getName(),
@@ -96,7 +96,7 @@ public function prepare(INotification $notification, string $languageCode): INot
9696
],
9797
)
9898
->setParsedSubject(str_replace(
99-
['{filename}'],
99+
['{name}'],
100100
[$node->getName()],
101101
$subject,
102102
))
@@ -127,16 +127,4 @@ protected function addActionButton(INotification $notification, string $label):
127127

128128
$notification->addParsedAction($action);
129129
}
130-
131-
/**
132-
* @throws NodeNotFoundException
133-
*/
134-
protected function getNode(int $fileId): Node {
135-
$nodes = $this->root->getById($fileId);
136-
if (empty($nodes)) {
137-
throw new NodeNotFoundException();
138-
}
139-
$node = reset($nodes);
140-
return $node;
141-
}
142130
}

apps/files_reminders/lib/Service/ReminderService.php

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,11 @@
3232
use OCA\FilesReminders\Db\Reminder;
3333
use OCA\FilesReminders\Db\ReminderMapper;
3434
use OCA\FilesReminders\Exception\UserNotFoundException;
35+
use OCA\FilesReminders\Model\RichReminder;
3536
use OCP\AppFramework\Db\DoesNotExistException;
37+
use OCP\Files\IRootFolder;
3638
use OCP\IURLGenerator;
39+
use OCP\IUser;
3740
use OCP\IUserManager;
3841
use OCP\Notification\IManager as INotificationManager;
3942
use Psr\Log\LoggerInterface;
@@ -44,9 +47,28 @@ public function __construct(
4447
protected IURLGenerator $urlGenerator,
4548
protected INotificationManager $notificationManager,
4649
protected ReminderMapper $reminderMapper,
50+
protected IRootFolder $root,
4751
protected LoggerInterface $logger,
4852
) {}
4953

54+
public function get(int $id): RichReminder {
55+
$reminder = $this->reminderMapper->find($id);
56+
return new RichReminder($reminder, $this->root);
57+
}
58+
59+
/**
60+
* @return RichReminder[]
61+
*/
62+
public function getAll(?IUser $user = null) {
63+
$reminders = ($user !== null)
64+
? $this->reminderMapper->findAllForUser($user)
65+
: $this->reminderMapper->findAll();
66+
return array_map(
67+
fn (Reminder $reminder) => new RichReminder($reminder, $this->root),
68+
$reminders,
69+
);
70+
}
71+
5072
/**
5173
* @throws DoesNotExistException
5274
* @throws UserNotFoundException
@@ -67,7 +89,7 @@ public function send(Reminder $reminder): void {
6789
->setIcon($this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('files', 'folder.svg')))
6890
->setUser($user->getUID())
6991
->setObject('reminder', (string)$reminder->getId())
70-
->setSubject('reminder-due', ['fileId' => $reminder->getFileId()])
92+
->setSubject('reminder-due')
7193
->setDateTime(DateTime::createFromFormat('U', (string)$reminder->getRemindAt()));
7294

7395
try {

0 commit comments

Comments
 (0)