Fix autolinking issues in the wiki. Fixes bug #11086.

The query for finding titles returns multiple title for each asset.
Guarantee that the latest title wins.  Do not escape characters in
the hash key, since that creates NEW hash entries, and all keys
are quotemeta'ed later anyway.
This commit is contained in:
Colin Kuskie 2009-10-22 10:26:12 -07:00
parent 4c4fbff712
commit abb60f10ea
2 changed files with 24 additions and 12 deletions

View file

@ -6,6 +6,7 @@
- fixed #11063: template_attachments
- fixed #11002: Matrix shows backend stuff on load
- added #10082: Unarchive all collaboration posts
- fixed #11086: bad urls in wiki
7.8.2
- Added scheduled vendor payout workflow activity. (Special thanks to Martin @ Oqapi)

View file

@ -159,7 +159,7 @@ sub appendSearchBoxVars {
#-------------------------------------------------------------------
=head2 autolinkHtml ($html)
=head2 autolinkHtml ($html, [options])
Scan HTML for words and phrases that match wiki titles, and automatically
link them to those wiki pages. Returns the modified HTML.
@ -168,6 +168,14 @@ link them to those wiki pages. Returns the modified HTML.
The HTML to scan.
=head3 options
Either a hashref, or a hash of options.
=head4 skipTitles
An array reference of titles that should not be autolinked.
=cut
sub autolinkHtml {
@ -175,18 +183,21 @@ sub autolinkHtml {
my $html = shift;
# opts is always the last parameter, and a hash ref
my %opts = ref $_[-1] eq 'HASH' ? %{pop @_} : ();
my $skipTitles = $opts{skipTitles} || [];
$opts{skipTitles} ||= [];
# LC all the skip titles once, for efficiency
my @skipTitles = map { lc $_ } @{ $opts{skipTitles} };
# TODO: ignore caching for now, but maybe do it later.
my %mapping = $self->session->db->buildHash("SELECT LOWER(d.title), d.url FROM asset AS i INNER JOIN assetData AS d ON i.assetId = d.assetId WHERE i.parentId = ? and className='WebGUI::Asset::WikiPage' and i.state='published' and d.status='approved'", [$self->getId]);
foreach my $key (keys %mapping) {
if (grep {lc $_ eq $key} @$skipTitles) {
delete $mapping{$key};
next;
}
$key =~ s{\(}{\\\(}gxms; # escape parens
$key =~ s{\)}{\\\)}gxms; # escape parens
$mapping{$key} = $self->session->url->gateway($mapping{$key});
}
# This query returns multiple entries for each asset, so we order by revisionDate and count on the hash to only have the
# latest version.
my %mapping = $self->session->db->buildHash("SELECT LOWER(d.title), d.url FROM asset AS i INNER JOIN assetData AS d ON i.assetId = d.assetId WHERE i.parentId = ? and className='WebGUI::Asset::WikiPage' and i.state='published' and d.status='approved' order by d.revisionDate ASC", [$self->getId]);
TITLE: foreach my $title (keys %mapping) {
my $url = delete $mapping{$title};
##isIn short circuits and is faster than grep and/or first
next TITLE if isIn($title, @skipTitles);
$mapping{$title} = $self->session->url->gateway($url);
}
return $html unless %mapping;
# sort by length so it prefers matching longer titles
my $matchString = join('|', map{quotemeta} sort {length($b) <=> length($a)} keys %mapping);