diff --git a/docs/changelog/7.x.x.txt b/docs/changelog/7.x.x.txt index 1aa2417e6..48c02a583 100644 --- a/docs/changelog/7.x.x.txt +++ b/docs/changelog/7.x.x.txt @@ -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) diff --git a/lib/WebGUI/Asset/Wobject/WikiMaster.pm b/lib/WebGUI/Asset/Wobject/WikiMaster.pm index 1d4d8829d..de7436c7b 100644 --- a/lib/WebGUI/Asset/Wobject/WikiMaster.pm +++ b/lib/WebGUI/Asset/Wobject/WikiMaster.pm @@ -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);