* (bug 14080) Short notation links to subpages didn't work in edit summaries
authorBrion Vibber <brion@users.mediawiki.org>
Mon, 20 Jul 2009 02:07:56 +0000 (02:07 +0000)
committerBrion Vibber <brion@users.mediawiki.org>
Mon, 20 Jul 2009 02:07:56 +0000 (02:07 +0000)
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
includes/Linker.php
includes/parser/Parser.php
maintenance/parserTests.txt

index 10772fe..c2632a4 100644 (file)
@@ -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 ==
 
index 93ac43d..7e2f131 100644 (file)
@@ -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
index 7f71aba..2ff2083 100644 (file)
@@ -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 );
        }
 
        /**#@+
index a2d0ab5..898c401 100644 (file)
@@ -7358,10 +7358,30 @@ I like the [[Main Page]] a lot
 I like the <a href="/wiki/Main_Page" title="Main Page">Main Page</a> 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 <a href="/wiki/Main_Page" title="Main Page">best pages</a> 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 <a href="/wiki/Main_Page" title="Main Page">best pages</a> 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
 <span class="autocomment"><a href="#External_links">→</a>External links: </span> 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 <a href="/wiki/Subpage_test/subpage" title="Subpage test/subpage">/subpage</a> 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 <a href="/wiki/Subpage_test/subpage" title="Subpage test/subpage">neat little page</a> 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 <a href="/index.php?title=/subpage&amp;action=edit&amp;redlink=1" class="new" title="/subpage (page does not exist)">/subpage</a> here...
+!!end
+
 
 TODO:
 more images