Merge pull request #58981 from nextcloud/backport/58974/stable33

[stable33] fix(comments): Don't return mentions in markdown code (by default)
This commit is contained in:
Andy Scherzinger 2026-03-17 10:03:29 +01:00 committed by GitHub
commit cae29df077
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 54 additions and 5 deletions

View file

@ -184,16 +184,25 @@ class Comment implements IComment {
/**
* returns an array containing mentions that are included in the comment
*
* @param bool $supportMarkdown
* @return array each mention provides a 'type' and an 'id', see example below
* @psalm-return list<array{type: 'guest'|'email'|'federated_group'|'group'|'federated_team'|'team'|'federated_user'|'user', id: non-empty-lowercase-string}>
* @since 33.0.1 Parameter $supportMarkdown was added to decide if mentions inside markdown code blocks should be ignored (default to true)
* @since 30.0.2 Type 'email' is supported
* @since 29.0.0 Types 'federated_group', 'federated_team', 'team' and 'federated_user' are supported
* @since 23.0.0 Type 'group' is supported
* @since 17.0.0 Type 'guest' is supported
* @since 11.0.0
*/
public function getMentions(): array {
$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);
public function getMentions(bool $supportMarkdown = true): array {
$message = $this->getMessage();
if ($supportMarkdown) {
// Strip fenced code blocks and inline code so mentions inside them are ignored
$message = preg_replace('/^```.*?^```|^~~~.*?^~~~/sm', '', $message);
$message = preg_replace('/`[^`\n]*`/', '', $message);
}
$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);
if (!$ok || !isset($mentions[0])) {
return [];
}

View file

@ -123,15 +123,17 @@ interface IComment {
/**
* returns an array containing mentions that are included in the comment
*
* @param bool $supportMarkdown
* @return array each mention provides a 'type' and an 'id', see example below
* @psalm-return list<array{type: 'guest'|'email'|'federated_group'|'group'|'federated_team'|'team'|'federated_user'|'user', id: non-empty-lowercase-string}>
* @since 33.0.1 Parameter $supportMarkdown was added to decide if mentions inside markdown code blocks should be ignored (default to true)
* @since 30.0.2 Type 'email' is supported
* @since 29.0.0 Types 'federated_group', 'federated_team', 'team' and 'federated_user' are supported
* @since 23.0.0 Type 'group' is supported
* @since 17.0.0 Type 'guest' is supported
* @since 11.0.0
*/
public function getMentions();
public function getMentions(bool $supportMarkdown = true);
/**
* returns the verb of the comment

View file

@ -202,17 +202,55 @@ class CommentTest extends TestCase {
['type' => 'email', 'id' => 'aa23d315de327cfc330f0401ea061005b2b0cdd45ec8346f12664dd1f34cb886'],
],
],
[
'Mention @alice but not `@bob` inside inline code',
[['type' => 'user', 'id' => 'alice']],
],
[
'Mention @alice but not `Hello @bob there` inside inline code',
[['type' => 'user', 'id' => 'alice']],
],
[
"Mention ` user @alice\nAs it's just 2 ` accents",
[['type' => 'user', 'id' => 'alice']],
],
[
'Mention @alice and @bob but not `Hello @bob there` inside inline code',
[['type' => 'user', 'id' => 'alice'], ['type' => 'user', 'id' => 'bob']],
],
[
"Mention @alice but not in fenced code block\n```\n@bob @charlie\n```\nend",
[['type' => 'user', 'id' => 'alice']],
],
[
"Mention @alice but not in tilde code block\n~~~\n@bob\n~~~\nend",
[['type' => 'user', 'id' => 'alice']],
],
[
'No mentions at all in `@alice` and `@bob`',
[],
],
[
"@alice\n```\n@bob\n```\n@charlie",
[['type' => 'user', 'id' => 'charlie'], ['type' => 'user', 'id' => 'alice']],
],
[
"@alice\n```\n@bob\n```\n@charlie",
[['type' => 'user', 'id' => 'charlie'], ['type' => 'user', 'id' => 'alice'], ['type' => 'user', 'id' => 'bob']],
null,
false,
],
];
}
#[DataProvider(methodName: 'mentionsProvider')]
public function testMentions(string $message, array $expectedMentions, ?string $author = null): void {
public function testMentions(string $message, array $expectedMentions, ?string $author = null, bool $markdown = true): void {
$comment = new Comment();
$comment->setMessage($message);
if (!is_null($author)) {
$comment->setActor('user', $author);
}
$mentions = $comment->getMentions();
$mentions = $comment->getMentions($markdown);
$this->assertSame($expectedMentions, $mentions);
}
}