Skip to content

Commit 83cff31

Browse files
authored
Merge pull request #12009 from nextcloud/feature/noid/populate-notification-message-with-the-comment
Populate the mention-notification with the actual message
2 parents 3a6b525 + d295ff5 commit 83cff31

File tree

1 file changed

+99
-41
lines changed

1 file changed

+99
-41
lines changed

apps/comments/lib/Notification/Notifier.php

Lines changed: 99 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,12 @@
2424

2525
namespace OCA\Comments\Notification;
2626

27+
use OCP\Comments\IComment;
2728
use OCP\Comments\ICommentsManager;
2829
use OCP\Comments\NotFoundException;
2930
use OCP\Files\IRootFolder;
3031
use OCP\IURLGenerator;
32+
use OCP\IUser;
3133
use OCP\IUserManager;
3234
use OCP\L10N\IFactory;
3335
use OCP\Notification\INotification;
@@ -83,17 +85,17 @@ public function prepare(INotification $notification, $languageCode) {
8385
$l = $this->l10nFactory->get('comments', $languageCode);
8486
$displayName = $comment->getActorId();
8587
$isDeletedActor = $comment->getActorType() === ICommentsManager::DELETED_USER;
86-
if($comment->getActorType() === 'users') {
88+
if ($comment->getActorType() === 'users') {
8789
$commenter = $this->userManager->get($comment->getActorId());
88-
if(!is_null($commenter)) {
90+
if ($commenter instanceof IUser) {
8991
$displayName = $commenter->getDisplayName();
9092
}
9193
}
9294

9395
switch($notification->getSubject()) {
9496
case 'mention':
9597
$parameters = $notification->getSubjectParameters();
96-
if($parameters[0] !== 'files') {
98+
if ($parameters[0] !== 'files') {
9799
throw new \InvalidArgumentException('Unsupported comment object');
98100
}
99101
$userFolder = $this->rootFolder->getUserFolder($notification->getUser());
@@ -103,47 +105,41 @@ public function prepare(INotification $notification, $languageCode) {
103105
}
104106
$node = $nodes[0];
105107

108+
$path = rtrim($node->getPath(), '/');
109+
if (strpos($path, '/' . $notification->getUser() . '/files/') === 0) {
110+
// Remove /user/files/...
111+
$fullPath = $path;
112+
list(,,, $path) = explode('/', $fullPath, 4);
113+
}
114+
115+
$subjectParameters = [
116+
'file' => [
117+
'type' => 'file',
118+
'id' => $comment->getObjectId(),
119+
'name' => $node->getName(),
120+
'path' => $path,
121+
'link' => $this->url->linkToRouteAbsolute('files.viewcontroller.showFile', ['fileid' => $comment->getObjectId()]),
122+
],
123+
];
124+
106125
if ($isDeletedActor) {
107-
$notification->setParsedSubject($l->t(
108-
'You were mentioned on “%s”, in a comment by a user that has since been deleted',
109-
[$node->getName()]
110-
))
111-
->setRichSubject(
112-
$l->t('You were mentioned on “{file}”, in a comment by a user that has since been deleted'),
113-
[
114-
'file' => [
115-
'type' => 'file',
116-
'id' => $comment->getObjectId(),
117-
'name' => $node->getName(),
118-
'path' => $node->getPath(),
119-
'link' => $this->url->linkToRouteAbsolute('files.viewcontroller.showFile', ['fileid' => $comment->getObjectId()]),
120-
],
121-
]
122-
);
126+
$subject = $l->t('You were mentioned on “{file}”, in a comment by a user that has since been deleted');
123127
} else {
124-
$notification->setParsedSubject($l->t(
125-
'%1$s mentioned you in a comment on “%2$s”',
126-
[$displayName, $node->getName()]
127-
))
128-
->setRichSubject(
129-
$l->t('{user} mentioned you in a comment on “{file}”'),
130-
[
131-
'user' => [
132-
'type' => 'user',
133-
'id' => $comment->getActorId(),
134-
'name' => $displayName,
135-
],
136-
'file' => [
137-
'type' => 'file',
138-
'id' => $comment->getObjectId(),
139-
'name' => $node->getName(),
140-
'path' => $node->getPath(),
141-
'link' => $this->url->linkToRouteAbsolute('files.viewcontroller.showFile', ['fileid' => $comment->getObjectId()]),
142-
],
143-
]
144-
);
128+
$subject = $l->t('{user} mentioned you in a comment on “{file}”');
129+
$subjectParameters['user'] = [
130+
'type' => 'user',
131+
'id' => $comment->getActorId(),
132+
'name' => $displayName,
133+
];
145134
}
146-
$notification->setIcon($this->url->getAbsoluteURL($this->url->imagePath('core', 'actions/comment.svg')))
135+
136+
list($message, $messageParameters) = $this->commentToRichMessage($comment);
137+
138+
$notification->setRichSubject($subject, $subjectParameters)
139+
->setParsedSubject($this->richToParsed($subject, $subjectParameters))
140+
->setRichMessage($message, $messageParameters)
141+
->setParsedMessage($this->richToParsed($message, $messageParameters))
142+
->setIcon($this->url->getAbsoluteURL($this->url->imagePath('core', 'actions/comment.svg')))
147143
->setLink($this->url->linkToRouteAbsolute(
148144
'comments.Notifications.view',
149145
['id' => $comment->getId()])
@@ -157,4 +153,66 @@ public function prepare(INotification $notification, $languageCode) {
157153
}
158154

159155
}
156+
157+
public function commentToRichMessage(IComment $comment): array {
158+
$message = $comment->getMessage();
159+
$messageParameters = [];
160+
161+
$mentionTypeCount = [];
162+
163+
$mentions = $comment->getMentions();
164+
foreach ($mentions as $mention) {
165+
if ($mention['type'] === 'user') {
166+
$user = $this->userManager->get($mention['id']);
167+
if (!$user instanceof IUser) {
168+
continue;
169+
}
170+
}
171+
172+
if (!array_key_exists($mention['type'], $mentionTypeCount)) {
173+
$mentionTypeCount[$mention['type']] = 0;
174+
}
175+
$mentionTypeCount[$mention['type']]++;
176+
177+
// To keep a limited character set in parameter IDs ([a-zA-Z0-9-])
178+
// the mention parameter ID does not include the mention ID (which
179+
// could contain characters like '@' for user IDs) but a one-based
180+
// index of the mentions of that type.
181+
$mentionParameterId = 'mention-' . $mention['type'] . $mentionTypeCount[$mention['type']];
182+
183+
$message = str_replace('@' . $mention['id'], '{' . $mentionParameterId . '}', $message);
184+
185+
try {
186+
$displayName = $this->commentsManager->resolveDisplayName($mention['type'], $mention['id']);
187+
} catch (\OutOfBoundsException $e) {
188+
// There is no registered display name resolver for the mention
189+
// type, so the client decides what to display.
190+
$displayName = '';
191+
}
192+
193+
$messageParameters[$mentionParameterId] = [
194+
'type' => $mention['type'],
195+
'id' => $mention['id'],
196+
'name' => $displayName
197+
];
198+
}
199+
200+
return [$message, $messageParameters];
201+
}
202+
203+
public function richToParsed(string $message, array $parameters): string {
204+
$placeholders = $replacements = [];
205+
foreach ($parameters as $placeholder => $parameter) {
206+
$placeholders[] = '{' . $placeholder . '}';
207+
if ($parameter['type'] === 'user') {
208+
$replacements[] = '@' . $parameter['name'];
209+
} else if ($parameter['type'] === 'file') {
210+
$replacements[] = $parameter['path'];
211+
} else {
212+
$replacements[] = $parameter['name'];
213+
}
214+
}
215+
216+
return str_replace($placeholders, $replacements, $message);
217+
}
160218
}

0 commit comments

Comments
 (0)