linkifier: Order linkifiers by id on query.

This explicitly enforces ordering on the linkifiers. This is useful when
there are overlapping linkifier patterns that matches the same text. In
our current linkifier implementation, this order affects how the
patterns are handled in the markdown processor, with the earlier ones
being prioritized.

Signed-off-by: Zixuan James Li <p359101898@gmail.com>
This commit is contained in:
Zixuan James Li 2022-12-01 18:37:35 -05:00 committed by Tim Abbott
parent 4602c34108
commit 5f4d857d3c
2 changed files with 18 additions and 1 deletions

View File

@ -1338,7 +1338,7 @@ def realm_filters_for_realm(realm_id: int) -> List[Tuple[str, str, int]]:
@cache_with_key(get_linkifiers_cache_key, timeout=3600 * 24 * 7) @cache_with_key(get_linkifiers_cache_key, timeout=3600 * 24 * 7)
def linkifiers_for_realm_remote_cache(realm_id: int) -> List[LinkifierDict]: def linkifiers_for_realm_remote_cache(realm_id: int) -> List[LinkifierDict]:
linkifiers = [] linkifiers = []
for linkifier in RealmFilter.objects.filter(realm_id=realm_id): for linkifier in RealmFilter.objects.filter(realm_id=realm_id).order_by("id"):
linkifiers.append( linkifiers.append(
LinkifierDict( LinkifierDict(
pattern=linkifier.pattern, pattern=linkifier.pattern,

View File

@ -1546,6 +1546,23 @@ class MarkdownTest(ZulipTestCase):
flush() flush()
self.assertFalse(realm_in_local_linkifiers_cache(realm.id)) self.assertFalse(realm_in_local_linkifiers_cache(realm.id))
def test_linkifier_precedence(self) -> None:
realm = self.example_user("hamlet").realm
# The insertion order should not affect the fact that the linkifiers are ordered by id.
# Note that we might later switch to a different field to order the linkifiers.
sequence = (10, 3, 11, 2, 4, 5, 6)
for cur_precedence in sequence:
linkifier = RealmFilter(
id=cur_precedence,
realm=realm,
pattern=f"abc{cur_precedence}",
url_format_string="http://foo.com",
)
linkifier.save()
linkifiers = linkifiers_for_realm(realm.id)
for index, cur_precedence in enumerate(sorted(sequence)):
self.assertEqual(linkifiers[index]["id"], cur_precedence)
def test_realm_patterns_negative(self) -> None: def test_realm_patterns_negative(self) -> None:
realm = get_realm("zulip") realm = get_realm("zulip")
RealmFilter( RealmFilter(