diff --git a/lib/private/Comments/Comment.php b/lib/private/Comments/Comment.php index 7190f252c8232..551b9d29e29d0 100644 --- a/lib/private/Comments/Comment.php +++ b/lib/private/Comments/Comment.php @@ -184,16 +184,25 @@ public function setMessage($message, $maxLength = self::MAX_MESSAGE_LENGTH): ICo /** * 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 + * @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(?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(? + * @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 diff --git a/tests/lib/Comments/CommentTest.php b/tests/lib/Comments/CommentTest.php index 670ccc69e1218..67d84d4ddbe9b 100644 --- a/tests/lib/Comments/CommentTest.php +++ b/tests/lib/Comments/CommentTest.php @@ -202,17 +202,55 @@ public static function mentionsProvider(): array { ['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); } }