From 43bf053fd0e19e6a126c9c030846cced2f758f0f Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Mon, 20 Jul 2009 02:07:56 +0000 Subject: [PATCH] * (bug 14080) Short notation links to subpages didn't work in edit summaries Moved Parser::maybeDoSubpage guts to Linker to call from both locations. Added some parser test cases. Note that this might not behave exactly like the main parser in cases where the link text would get altered, but the links are functional. Yay! --- RELEASE-NOTES | 1 + includes/Linker.php | 90 ++++++++++++++++++++++++++++++++++--- includes/parser/Parser.php | 70 +---------------------------- maintenance/parserTests.txt | 59 +++++++++++++++++++++++- 4 files changed, 144 insertions(+), 76 deletions(-) diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 10772fe681..c2632a4500 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -300,6 +300,7 @@ this. Was used when mwEmbed was going to be an extension. * (bug 18751) Fix for buggage in profiling setup for some extensions on PHP 5.1 * (bug 17139) ts_resortTable inconsistent trimming makes date sorting fragile * (bug 19445) Change oldimage table to use ON UPDATE CASCADE for FK to image table. +* (bug 14080) Short notation links to subpages didn't work in edit summaries == API changes in 1.16 == diff --git a/includes/Linker.php b/includes/Linker.php index 93ac43def2..7e2f13169e 100644 --- a/includes/Linker.php +++ b/includes/Linker.php @@ -922,7 +922,7 @@ class Linker { # Render autocomments and make links: $comment = $this->formatAutoComments( $comment, $title, $local ); - $comment = $this->formatLinksInComment( $comment ); + $comment = $this->formatLinksInComment( $comment, $title ); wfProfileOut( __METHOD__ ); return $comment; @@ -1009,11 +1009,14 @@ class Linker { * @param string $comment Text to format links in * @return string */ - public function formatLinksInComment( $comment ) { - return preg_replace_callback( + public function formatLinksInComment( $comment, $title = null ) { + $this->commentContextTitle = $title; + $html = preg_replace_callback( '/\[\[:?(.*?)(\|(.*?))*\]\]([^[]*)/', array( $this, 'formatLinksInCommentCallback' ), $comment ); + unset( $this->commentContextTitle ); + return $html; } protected function formatLinksInCommentCallback( $match ) { @@ -1052,15 +1055,92 @@ class Linker { if (isset($match[1][0]) && $match[1][0] == ':') $match[1] = substr($match[1], 1); list( $inside, $trail ) = Linker::splitTrail( $trail ); + + $linkText = $text; + $linkTarget = Linker::normalizeSubpageLink( $this->commentContextTitle, + $match[1], $linkText ); + $thelink = $this->link( - Title::newFromText( $match[1] ), - $text . $inside + Title::newFromText( $linkTarget ), + $linkText . $inside ) . $trail; } $comment = preg_replace( $linkRegexp, StringUtils::escapeRegexReplacement( $thelink ), $comment, 1 ); return $comment; } + + static function normalizeSubpageLink( $contextTitle, $target, &$text ) { + # Valid link forms: + # Foobar -- normal + # :Foobar -- override special treatment of prefix (images, language links) + # /Foobar -- convert to CurrentPage/Foobar + # /Foobar/ -- convert to CurrentPage/Foobar, strip the initial / from text + # ../ -- convert to CurrentPage, from CurrentPage/CurrentSubPage + # ../Foobar -- convert to CurrentPage/Foobar, from CurrentPage/CurrentSubPage + + wfProfileIn( __METHOD__ ); + $ret = $target; # default return value is no change + + # Some namespaces don't allow subpages, + # so only perform processing if subpages are allowed + if( $contextTitle && MWNamespace::hasSubpages( $contextTitle->getNamespace() ) ) { + $hash = strpos( $target, '#' ); + if( $hash !== false ) { + $suffix = substr( $target, $hash ); + $target = substr( $target, 0, $hash ); + } else { + $suffix = ''; + } + # bug 7425 + $target = trim( $target ); + # Look at the first character + if( $target != '' && $target{0} === '/' ) { + # / at end means we don't want the slash to be shown + $m = array(); + $trailingSlashes = preg_match_all( '%(/+)$%', $target, $m ); + if( $trailingSlashes ) { + $noslash = $target = substr( $target, 1, -strlen($m[0][0]) ); + } else { + $noslash = substr( $target, 1 ); + } + + $ret = $contextTitle->getPrefixedText(). '/' . trim($noslash) . $suffix; + if( '' === $text ) { + $text = $target . $suffix; + } # this might be changed for ugliness reasons + } else { + # check for .. subpage backlinks + $dotdotcount = 0; + $nodotdot = $target; + while( strncmp( $nodotdot, "../", 3 ) == 0 ) { + ++$dotdotcount; + $nodotdot = substr( $nodotdot, 3 ); + } + if($dotdotcount > 0) { + $exploded = explode( '/', $contextTitle->GetPrefixedText() ); + if( count( $exploded ) > $dotdotcount ) { # not allowed to go below top level page + $ret = implode( '/', array_slice( $exploded, 0, -$dotdotcount ) ); + # / at the end means don't show full path + if( substr( $nodotdot, -1, 1 ) === '/' ) { + $nodotdot = substr( $nodotdot, 0, -1 ); + if( '' === $text ) { + $text = $nodotdot . $suffix; + } + } + $nodotdot = trim( $nodotdot ); + if( $nodotdot != '' ) { + $ret .= '/' . $nodotdot; + } + $ret .= $suffix; + } + } + } + } + + wfProfileOut( __METHOD__ ); + return $ret; + } /** * Wrap a comment in standard punctuation and formatting if diff --git a/includes/parser/Parser.php b/includes/parser/Parser.php index 7f71aba312..2ff208360a 100644 --- a/includes/parser/Parser.php +++ b/includes/parser/Parser.php @@ -1840,75 +1840,7 @@ class Parser * @private */ function maybeDoSubpageLink($target, &$text) { - # Valid link forms: - # Foobar -- normal - # :Foobar -- override special treatment of prefix (images, language links) - # /Foobar -- convert to CurrentPage/Foobar - # /Foobar/ -- convert to CurrentPage/Foobar, strip the initial / from text - # ../ -- convert to CurrentPage, from CurrentPage/CurrentSubPage - # ../Foobar -- convert to CurrentPage/Foobar, from CurrentPage/CurrentSubPage - - wfProfileIn( __METHOD__ ); - $ret = $target; # default return value is no change - - # Some namespaces don't allow subpages, - # so only perform processing if subpages are allowed - if( $this->areSubpagesAllowed() ) { - $hash = strpos( $target, '#' ); - if( $hash !== false ) { - $suffix = substr( $target, $hash ); - $target = substr( $target, 0, $hash ); - } else { - $suffix = ''; - } - # bug 7425 - $target = trim( $target ); - # Look at the first character - if( $target != '' && $target{0} === '/' ) { - # / at end means we don't want the slash to be shown - $m = array(); - $trailingSlashes = preg_match_all( '%(/+)$%', $target, $m ); - if( $trailingSlashes ) { - $noslash = $target = substr( $target, 1, -strlen($m[0][0]) ); - } else { - $noslash = substr( $target, 1 ); - } - - $ret = $this->mTitle->getPrefixedText(). '/' . trim($noslash) . $suffix; - if( '' === $text ) { - $text = $target . $suffix; - } # this might be changed for ugliness reasons - } else { - # check for .. subpage backlinks - $dotdotcount = 0; - $nodotdot = $target; - while( strncmp( $nodotdot, "../", 3 ) == 0 ) { - ++$dotdotcount; - $nodotdot = substr( $nodotdot, 3 ); - } - if($dotdotcount > 0) { - $exploded = explode( '/', $this->mTitle->GetPrefixedText() ); - if( count( $exploded ) > $dotdotcount ) { # not allowed to go below top level page - $ret = implode( '/', array_slice( $exploded, 0, -$dotdotcount ) ); - # / at the end means don't show full path - if( substr( $nodotdot, -1, 1 ) === '/' ) { - $nodotdot = substr( $nodotdot, 0, -1 ); - if( '' === $text ) { - $text = $nodotdot . $suffix; - } - } - $nodotdot = trim( $nodotdot ); - if( $nodotdot != '' ) { - $ret .= '/' . $nodotdot; - } - $ret .= $suffix; - } - } - } - } - - wfProfileOut( __METHOD__ ); - return $ret; + return Linker::normalizeSubpageLink( $this->mTitle, $target, $text ); } /**#@+ diff --git a/maintenance/parserTests.txt b/maintenance/parserTests.txt index a2d0ab52b3..898c4011ff 100644 --- a/maintenance/parserTests.txt +++ b/maintenance/parserTests.txt @@ -7358,10 +7358,30 @@ I like the [[Main Page]] a lot I like the Main Page a lot !!end +!! test +Edit comment with link and link text +!! options +comment +!! input +I like the [[Main Page|best pages]] a lot +!! result +I like the best pages a lot +!!end + +!! test +Edit comment with link and link text with suffix +!! options +comment +!! input +I like the [[Main Page|best page]]s a lot +!! result +I like the best pages a lot +!!end + !! test Edit comment with section link (non-local, eg in history list) !! options -comment,title=[[Main Page]] +comment title=[[Main Page]] !! input /* External links */ removed bogus entries !! result @@ -7371,13 +7391,48 @@ comment,title=[[Main Page]] !! test Edit comment with section link (local, eg in diff view) !! options -comment,local,title=[[Main Page]] +comment local title=[[Main Page]] !! input /* External links */ removed bogus entries !! result →External links: removed bogus entries !!end +!! test +Edit comment with subpage link (bug 14080) +!! options +comment +subpage +title=[[Subpage test]] +!! input +Poked at a [[/subpage]] here... +!! result +Poked at a /subpage here... +!!end + +!! test +Edit comment with subpage link and link text (bug 14080) +!! options +comment +subpage +title=[[Subpage test]] +!! input +Poked at a [[/subpage|neat little page]] here... +!! result +Poked at a neat little page here... +!!end + +!! test +Edit comment with bogus subpage link in non-subpage NS (bug 14080) +!! options +comment +title=[[Subpage test]] +!! input +Poked at a [[/subpage]] here... +!! result +Poked at a /subpage here... +!!end + TODO: more images -- 2.20.1