Skip to content

Commit cae29df

Browse files
Merge pull request #58981 from nextcloud/backport/58974/stable33
[stable33] fix(comments): Don't return mentions in markdown code (by default)
2 parents bf0604e + e700027 commit cae29df

3 files changed

Lines changed: 54 additions & 5 deletions

File tree

lib/private/Comments/Comment.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,16 +184,25 @@ public function setMessage($message, $maxLength = self::MAX_MESSAGE_LENGTH): ICo
184184
/**
185185
* returns an array containing mentions that are included in the comment
186186
*
187+
* @param bool $supportMarkdown
187188
* @return array each mention provides a 'type' and an 'id', see example below
188189
* @psalm-return list<array{type: 'guest'|'email'|'federated_group'|'group'|'federated_team'|'team'|'federated_user'|'user', id: non-empty-lowercase-string}>
190+
* @since 33.0.1 Parameter $supportMarkdown was added to decide if mentions inside markdown code blocks should be ignored (default to true)
189191
* @since 30.0.2 Type 'email' is supported
190192
* @since 29.0.0 Types 'federated_group', 'federated_team', 'team' and 'federated_user' are supported
191193
* @since 23.0.0 Type 'group' is supported
192194
* @since 17.0.0 Type 'guest' is supported
193195
* @since 11.0.0
194196
*/
195-
public function getMentions(): array {
196-
$ok = preg_match_all("/\B(?<![^a-z0-9_\-@\.\'\s])@(\"(guest|email)\/[a-f0-9]+\"|\"(?:federated_)?(?:group|team|user){1}\/[a-z0-9_\-@\.\' \/:]+\"|\"[a-z0-9_\-@\.\' ]+\"|[a-z0-9_\-@\.\']+)/i", $this->getMessage(), $mentions);
197+
public function getMentions(bool $supportMarkdown = true): array {
198+
$message = $this->getMessage();
199+
if ($supportMarkdown) {
200+
// Strip fenced code blocks and inline code so mentions inside them are ignored
201+
$message = preg_replace('/^```.*?^```|^~~~.*?^~~~/sm', '', $message);
202+
$message = preg_replace('/`[^`\n]*`/', '', $message);
203+
}
204+
205+
$ok = preg_match_all("/\B(?<![^a-z0-9_\-@\.\'\s])@(\"(guest|email)\/[a-f0-9]+\"|\"(?:federated_)?(?:group|team|user){1}\/[a-z0-9_\-@\.\' \/:]+\"|\"[a-z0-9_\-@\.\' ]+\"|[a-z0-9_\-@\.\']+)/i", $message, $mentions);
197206
if (!$ok || !isset($mentions[0])) {
198207
return [];
199208
}

lib/public/Comments/IComment.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,15 +123,17 @@ public function setMessage($message, $maxLength = self::MAX_MESSAGE_LENGTH);
123123
/**
124124
* returns an array containing mentions that are included in the comment
125125
*
126+
* @param bool $supportMarkdown
126127
* @return array each mention provides a 'type' and an 'id', see example below
127128
* @psalm-return list<array{type: 'guest'|'email'|'federated_group'|'group'|'federated_team'|'team'|'federated_user'|'user', id: non-empty-lowercase-string}>
129+
* @since 33.0.1 Parameter $supportMarkdown was added to decide if mentions inside markdown code blocks should be ignored (default to true)
128130
* @since 30.0.2 Type 'email' is supported
129131
* @since 29.0.0 Types 'federated_group', 'federated_team', 'team' and 'federated_user' are supported
130132
* @since 23.0.0 Type 'group' is supported
131133
* @since 17.0.0 Type 'guest' is supported
132134
* @since 11.0.0
133135
*/
134-
public function getMentions();
136+
public function getMentions(bool $supportMarkdown = true);
135137

136138
/**
137139
* returns the verb of the comment

tests/lib/Comments/CommentTest.php

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,17 +202,55 @@ public static function mentionsProvider(): array {
202202
['type' => 'email', 'id' => 'aa23d315de327cfc330f0401ea061005b2b0cdd45ec8346f12664dd1f34cb886'],
203203
],
204204
],
205+
[
206+
'Mention @alice but not `@bob` inside inline code',
207+
[['type' => 'user', 'id' => 'alice']],
208+
],
209+
[
210+
'Mention @alice but not `Hello @bob there` inside inline code',
211+
[['type' => 'user', 'id' => 'alice']],
212+
],
213+
[
214+
"Mention ` user @alice\nAs it's just 2 ` accents",
215+
[['type' => 'user', 'id' => 'alice']],
216+
],
217+
[
218+
'Mention @alice and @bob but not `Hello @bob there` inside inline code',
219+
[['type' => 'user', 'id' => 'alice'], ['type' => 'user', 'id' => 'bob']],
220+
],
221+
[
222+
"Mention @alice but not in fenced code block\n```\n@bob @charlie\n```\nend",
223+
[['type' => 'user', 'id' => 'alice']],
224+
],
225+
[
226+
"Mention @alice but not in tilde code block\n~~~\n@bob\n~~~\nend",
227+
[['type' => 'user', 'id' => 'alice']],
228+
],
229+
[
230+
'No mentions at all in `@alice` and `@bob`',
231+
[],
232+
],
233+
[
234+
"@alice\n```\n@bob\n```\n@charlie",
235+
[['type' => 'user', 'id' => 'charlie'], ['type' => 'user', 'id' => 'alice']],
236+
],
237+
[
238+
"@alice\n```\n@bob\n```\n@charlie",
239+
[['type' => 'user', 'id' => 'charlie'], ['type' => 'user', 'id' => 'alice'], ['type' => 'user', 'id' => 'bob']],
240+
null,
241+
false,
242+
],
205243
];
206244
}
207245

208246
#[DataProvider(methodName: 'mentionsProvider')]
209-
public function testMentions(string $message, array $expectedMentions, ?string $author = null): void {
247+
public function testMentions(string $message, array $expectedMentions, ?string $author = null, bool $markdown = true): void {
210248
$comment = new Comment();
211249
$comment->setMessage($message);
212250
if (!is_null($author)) {
213251
$comment->setActor('user', $author);
214252
}
215-
$mentions = $comment->getMentions();
253+
$mentions = $comment->getMentions($markdown);
216254
$this->assertSame($expectedMentions, $mentions);
217255
}
218256
}

0 commit comments

Comments
 (0)