* (bug 11560) Fix broken HTML output from weird link nesting in edit comments.
authorBrion Vibber <brion@users.mediawiki.org>
Thu, 4 Oct 2007 18:59:50 +0000 (18:59 +0000)
committerBrion Vibber <brion@users.mediawiki.org>
Thu, 4 Oct 2007 18:59:50 +0000 (18:59 +0000)
  Nested links (as in image caption text) still don't work _right_ but they're
  less wrong.

Linker::formatComment() used a multi-pass run without proper protections,
making it possible for a later 'link' to erase a previous pass's start
or end tag. Switched to a single-pass run with preg_replace_callback which
avoids this.

RELEASE-NOTES
includes/Linker.php

index 495aa4d..6d395da 100644 (file)
@@ -84,6 +84,9 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN
 * (bug 11478) Fix undefined method call in file deletion interface
 * (bug 278) Search results no longer highlight incorrect partial word matches
 * Compatibility with incorrectly detected old-style DJVU mime types
+* (bug 11560) Fix broken HTML output from weird link nesting in edit comments.
+  Nested links (as in image caption text) still don't work _right_ but they're
+  less wrong.
 
 
 === API changes in 1.12 ===
index 1d187b8..e61578d 100644 (file)
@@ -988,42 +988,49 @@ class Linker {
         * Formats wiki links and media links in text; all other wiki formatting
         * is ignored
         *
+        * @fixme doesn't handle sub-links as in image thumb texts like the main parser
         * @param string $comment Text to format links in
         * @return string
         */
        public function formatLinksInComment( $comment ) {
+               return preg_replace_callback(
+                       '/\[\[:?(.*?)(\|(.*?))*\]\]([^[]*)/',
+                       array( $this, 'formatLinksInCommentCallback' ),
+                       $comment );
+       }
+       
+       protected function formatLinksInCommentCallback( $match ) {
                global $wgContLang;
 
                $medians = '(?:' . preg_quote( Namespace::getCanonicalName( NS_MEDIA ), '/' ) . '|';
                $medians .= preg_quote( $wgContLang->getNsText( NS_MEDIA ), '/' ) . '):';
+               
+               $comment = $match[0];
 
-               $match = array();
-               while(preg_match('/\[\[:?(.*?)(\|(.*?))*\]\](.*)$/',$comment,$match)) {
-                       # Handle link renaming [[foo|text]] will show link as "text"
-                       if( "" != $match[3] ) {
-                               $text = $match[3];
-                       } else {
-                               $text = $match[1];
-                       }
-                       $submatch = array();
-                       if( preg_match( '/^' . $medians . '(.*)$/i', $match[1], $submatch ) ) {
-                               # Media link; trail not supported.
-                               $linkRegexp = '/\[\[(.*?)\]\]/';
-                               $thelink = $this->makeMediaLink( $submatch[1], "", $text );
+               # Handle link renaming [[foo|text]] will show link as "text"
+               if( "" != $match[3] ) {
+                       $text = $match[3];
+               } else {
+                       $text = $match[1];
+               }
+               $submatch = array();
+               if( preg_match( '/^' . $medians . '(.*)$/i', $match[1], $submatch ) ) {
+                       # Media link; trail not supported.
+                       $linkRegexp = '/\[\[(.*?)\]\]/';
+                       $thelink = $this->makeMediaLink( $submatch[1], "", $text );
+               } else {
+                       # Other kind of link
+                       if( preg_match( $wgContLang->linkTrail(), $match[4], $submatch ) ) {
+                               $trail = $submatch[1];
                        } else {
-                               # Other kind of link
-                               if( preg_match( $wgContLang->linkTrail(), $match[4], $submatch ) ) {
-                                       $trail = $submatch[1];
-                               } else {
-                                       $trail = "";
-                               }
-                               $linkRegexp = '/\[\[(.*?)\]\]' . preg_quote( $trail, '/' ) . '/';
-                               if (isset($match[1][0]) && $match[1][0] == ':')
-                                       $match[1] = substr($match[1], 1);
-                               $thelink = $this->makeLink( $match[1], $text, "", $trail );
+                               $trail = "";
                        }
-                       $comment = preg_replace( $linkRegexp, StringUtils::escapeRegexReplacement( $thelink ), $comment, 1 );
+                       $linkRegexp = '/\[\[(.*?)\]\]' . preg_quote( $trail, '/' ) . '/';
+                       if (isset($match[1][0]) && $match[1][0] == ':')
+                               $match[1] = substr($match[1], 1);
+                       $thelink = $this->makeLink( $match[1], $text, "", $trail );
                }
+               $comment = preg_replace( $linkRegexp, StringUtils::escapeRegexReplacement( $thelink ), $comment, 1 );
 
                return $comment;
        }